1 /* simple-object.c -- simple routines to read and write object files. 2 Copyright 2010 Free Software Foundation, Inc. 3 Written by Ian Lance Taylor, Google. 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published by the 7 Free Software Foundation; either version 2, or (at your option) any 8 later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, 51 Franklin Street - Fifth Floor, 18 Boston, MA 02110-1301, USA. */ 19 20 #include "config.h" 21 #include "libiberty.h" 22 #include "simple-object.h" 23 24 #include <errno.h> 25 26 #ifdef HAVE_STDLIB_H 27 #include <stdlib.h> 28 #endif 29 30 #ifdef HAVE_STDINT_H 31 #include <stdint.h> 32 #endif 33 34 #ifdef HAVE_STRING_H 35 #include <string.h> 36 #endif 37 38 #ifdef HAVE_INTTYPES_H 39 #include <inttypes.h> 40 #endif 41 42 #ifndef SEEK_SET 43 #define SEEK_SET 0 44 #endif 45 46 #include "simple-object-common.h" 47 48 /* The known object file formats. */ 49 50 static const struct simple_object_functions * const format_functions[] = 51 { 52 &simple_object_elf_functions, 53 &simple_object_mach_o_functions, 54 &simple_object_coff_functions, 55 &simple_object_xcoff_functions 56 }; 57 58 /* Read data from a file using the simple_object error reporting 59 conventions. */ 60 61 int 62 simple_object_internal_read (int descriptor, off_t offset, 63 unsigned char *buffer, size_t size, 64 const char **errmsg, int *err) 65 { 66 ssize_t got; 67 68 if (lseek (descriptor, offset, SEEK_SET) < 0) 69 { 70 *errmsg = "lseek"; 71 *err = errno; 72 return 0; 73 } 74 75 got = read (descriptor, buffer, size); 76 if (got < 0) 77 { 78 *errmsg = "read"; 79 *err = errno; 80 return 0; 81 } 82 83 if ((size_t) got < size) 84 { 85 *errmsg = "file too short"; 86 *err = 0; 87 return 0; 88 } 89 90 return 1; 91 } 92 93 /* Write data to a file using the simple_object error reporting 94 conventions. */ 95 96 int 97 simple_object_internal_write (int descriptor, off_t offset, 98 const unsigned char *buffer, size_t size, 99 const char **errmsg, int *err) 100 { 101 ssize_t wrote; 102 103 if (lseek (descriptor, offset, SEEK_SET) < 0) 104 { 105 *errmsg = "lseek"; 106 *err = errno; 107 return 0; 108 } 109 110 wrote = write (descriptor, buffer, size); 111 if (wrote < 0) 112 { 113 *errmsg = "write"; 114 *err = errno; 115 return 0; 116 } 117 118 if ((size_t) wrote < size) 119 { 120 *errmsg = "short write"; 121 *err = 0; 122 return 0; 123 } 124 125 return 1; 126 } 127 128 /* Open for read. */ 129 130 simple_object_read * 131 simple_object_start_read (int descriptor, off_t offset, 132 const char *segment_name, const char **errmsg, 133 int *err) 134 { 135 unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN]; 136 size_t len, i; 137 138 if (!simple_object_internal_read (descriptor, offset, header, 139 SIMPLE_OBJECT_MATCH_HEADER_LEN, 140 errmsg, err)) 141 return NULL; 142 143 len = sizeof (format_functions) / sizeof (format_functions[0]); 144 for (i = 0; i < len; ++i) 145 { 146 void *data; 147 148 data = format_functions[i]->match (header, descriptor, offset, 149 segment_name, errmsg, err); 150 if (data != NULL) 151 { 152 simple_object_read *ret; 153 154 ret = XNEW (simple_object_read); 155 ret->descriptor = descriptor; 156 ret->offset = offset; 157 ret->functions = format_functions[i]; 158 ret->data = data; 159 return ret; 160 } 161 } 162 163 *errmsg = "file not recognized"; 164 *err = 0; 165 return NULL; 166 } 167 168 /* Find all sections. */ 169 170 const char * 171 simple_object_find_sections (simple_object_read *sobj, 172 int (*pfn) (void *, const char *, off_t, off_t), 173 void *data, 174 int *err) 175 { 176 return sobj->functions->find_sections (sobj, pfn, data, err); 177 } 178 179 /* Internal data passed to find_one_section. */ 180 181 struct find_one_section_data 182 { 183 /* The section we are looking for. */ 184 const char *name; 185 /* Where to store the section offset. */ 186 off_t *offset; 187 /* Where to store the section length. */ 188 off_t *length; 189 /* Set if the name is found. */ 190 int found; 191 }; 192 193 /* Internal function passed to find_sections. */ 194 195 static int 196 find_one_section (void *data, const char *name, off_t offset, off_t length) 197 { 198 struct find_one_section_data *fosd = (struct find_one_section_data *) data; 199 200 if (strcmp (name, fosd->name) != 0) 201 return 1; 202 203 *fosd->offset = offset; 204 *fosd->length = length; 205 fosd->found = 1; 206 207 /* Stop iteration. */ 208 return 0; 209 } 210 211 /* Find a section. */ 212 213 int 214 simple_object_find_section (simple_object_read *sobj, const char *name, 215 off_t *offset, off_t *length, 216 const char **errmsg, int *err) 217 { 218 struct find_one_section_data fosd; 219 220 fosd.name = name; 221 fosd.offset = offset; 222 fosd.length = length; 223 fosd.found = 0; 224 225 *errmsg = simple_object_find_sections (sobj, find_one_section, 226 (void *) &fosd, err); 227 if (*errmsg != NULL) 228 return 0; 229 if (!fosd.found) 230 return 0; 231 return 1; 232 } 233 234 /* Fetch attributes. */ 235 236 simple_object_attributes * 237 simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg, 238 int *err) 239 { 240 void *data; 241 simple_object_attributes *ret; 242 243 data = sobj->functions->fetch_attributes (sobj, errmsg, err); 244 if (data == NULL) 245 return NULL; 246 ret = XNEW (simple_object_attributes); 247 ret->functions = sobj->functions; 248 ret->data = data; 249 return ret; 250 } 251 252 /* Release an simple_object_read. */ 253 254 void 255 simple_object_release_read (simple_object_read *sobj) 256 { 257 sobj->functions->release_read (sobj->data); 258 XDELETE (sobj); 259 } 260 261 /* Merge attributes. */ 262 263 const char * 264 simple_object_attributes_merge (simple_object_attributes *to, 265 simple_object_attributes *from, 266 int *err) 267 { 268 if (to->functions != from->functions) 269 { 270 *err = 0; 271 return "different object file format"; 272 } 273 return to->functions->attributes_merge (to->data, from->data, err); 274 } 275 276 /* Release an attributes structure. */ 277 278 void 279 simple_object_release_attributes (simple_object_attributes *attrs) 280 { 281 attrs->functions->release_attributes (attrs->data); 282 XDELETE (attrs); 283 } 284 285 /* Start creating an object file. */ 286 287 simple_object_write * 288 simple_object_start_write (simple_object_attributes *attrs, 289 const char *segment_name, const char **errmsg, 290 int *err) 291 { 292 void *data; 293 simple_object_write *ret; 294 295 data = attrs->functions->start_write (attrs->data, errmsg, err); 296 if (data == NULL) 297 return NULL; 298 ret = XNEW (simple_object_write); 299 ret->functions = attrs->functions; 300 ret->segment_name = xstrdup (segment_name); 301 ret->sections = NULL; 302 ret->last_section = NULL; 303 ret->data = data; 304 return ret; 305 } 306 307 /* Start creating a section. */ 308 309 simple_object_write_section * 310 simple_object_write_create_section (simple_object_write *sobj, const char *name, 311 unsigned int align, 312 const char **errmsg ATTRIBUTE_UNUSED, 313 int *err ATTRIBUTE_UNUSED) 314 { 315 simple_object_write_section *ret; 316 317 ret = XNEW (simple_object_write_section); 318 ret->next = NULL; 319 ret->name = xstrdup (name); 320 ret->align = align; 321 ret->buffers = NULL; 322 ret->last_buffer = NULL; 323 324 if (sobj->last_section == NULL) 325 { 326 sobj->sections = ret; 327 sobj->last_section = ret; 328 } 329 else 330 { 331 sobj->last_section->next = ret; 332 sobj->last_section = ret; 333 } 334 335 return ret; 336 } 337 338 /* Add data to a section. */ 339 340 const char * 341 simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED, 342 simple_object_write_section *section, 343 const void *buffer, 344 size_t size, int copy, 345 int *err ATTRIBUTE_UNUSED) 346 { 347 struct simple_object_write_section_buffer *wsb; 348 349 wsb = XNEW (struct simple_object_write_section_buffer); 350 wsb->next = NULL; 351 wsb->size = size; 352 353 if (!copy) 354 { 355 wsb->buffer = buffer; 356 wsb->free_buffer = NULL; 357 } 358 else 359 { 360 wsb->free_buffer = (void *) XNEWVEC (char, size); 361 memcpy (wsb->free_buffer, buffer, size); 362 wsb->buffer = wsb->free_buffer; 363 } 364 365 if (section->last_buffer == NULL) 366 { 367 section->buffers = wsb; 368 section->last_buffer = wsb; 369 } 370 else 371 { 372 section->last_buffer->next = wsb; 373 section->last_buffer = wsb; 374 } 375 376 return NULL; 377 } 378 379 /* Write the complete object file. */ 380 381 const char * 382 simple_object_write_to_file (simple_object_write *sobj, int descriptor, 383 int *err) 384 { 385 return sobj->functions->write_to_file (sobj, descriptor, err); 386 } 387 388 /* Release an simple_object_write. */ 389 390 void 391 simple_object_release_write (simple_object_write *sobj) 392 { 393 simple_object_write_section *section; 394 395 free (sobj->segment_name); 396 397 section = sobj->sections; 398 while (section != NULL) 399 { 400 struct simple_object_write_section_buffer *buffer; 401 simple_object_write_section *next_section; 402 403 buffer = section->buffers; 404 while (buffer != NULL) 405 { 406 struct simple_object_write_section_buffer *next_buffer; 407 408 if (buffer->free_buffer != NULL) 409 XDELETEVEC (buffer->free_buffer); 410 next_buffer = buffer->next; 411 XDELETE (buffer); 412 buffer = next_buffer; 413 } 414 415 next_section = section->next; 416 free (section->name); 417 XDELETE (section); 418 section = next_section; 419 } 420 421 sobj->functions->release_write (sobj->data); 422 XDELETE (sobj); 423 } 424