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 if (lseek (descriptor, offset, SEEK_SET) < 0) 67 { 68 *errmsg = "lseek"; 69 *err = errno; 70 return 0; 71 } 72 73 do 74 { 75 ssize_t got = read (descriptor, buffer, size); 76 if (got == 0) 77 break; 78 else if (got > 0) 79 { 80 buffer += got; 81 size -= got; 82 } 83 else if (errno != EINTR) 84 { 85 *errmsg = "read"; 86 *err = errno; 87 return 0; 88 } 89 } 90 while (size > 0); 91 92 if (size > 0) 93 { 94 *errmsg = "file too short"; 95 *err = 0; 96 return 0; 97 } 98 99 return 1; 100 } 101 102 /* Write data to a file using the simple_object error reporting 103 conventions. */ 104 105 int 106 simple_object_internal_write (int descriptor, off_t offset, 107 const unsigned char *buffer, size_t size, 108 const char **errmsg, int *err) 109 { 110 if (lseek (descriptor, offset, SEEK_SET) < 0) 111 { 112 *errmsg = "lseek"; 113 *err = errno; 114 return 0; 115 } 116 117 do 118 { 119 ssize_t wrote = write (descriptor, buffer, size); 120 if (wrote == 0) 121 break; 122 else if (wrote > 0) 123 { 124 buffer += wrote; 125 size -= wrote; 126 } 127 else if (errno != EINTR) 128 { 129 *errmsg = "write"; 130 *err = errno; 131 return 0; 132 } 133 } 134 while (size > 0); 135 136 if (size > 0) 137 { 138 *errmsg = "short write"; 139 *err = 0; 140 return 0; 141 } 142 143 return 1; 144 } 145 146 /* Open for read. */ 147 148 simple_object_read * 149 simple_object_start_read (int descriptor, off_t offset, 150 const char *segment_name, const char **errmsg, 151 int *err) 152 { 153 unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN]; 154 size_t len, i; 155 156 if (!simple_object_internal_read (descriptor, offset, header, 157 SIMPLE_OBJECT_MATCH_HEADER_LEN, 158 errmsg, err)) 159 return NULL; 160 161 len = sizeof (format_functions) / sizeof (format_functions[0]); 162 for (i = 0; i < len; ++i) 163 { 164 void *data; 165 166 data = format_functions[i]->match (header, descriptor, offset, 167 segment_name, errmsg, err); 168 if (data != NULL) 169 { 170 simple_object_read *ret; 171 172 ret = XNEW (simple_object_read); 173 ret->descriptor = descriptor; 174 ret->offset = offset; 175 ret->functions = format_functions[i]; 176 ret->data = data; 177 return ret; 178 } 179 } 180 181 *errmsg = "file not recognized"; 182 *err = 0; 183 return NULL; 184 } 185 186 /* Find all sections. */ 187 188 const char * 189 simple_object_find_sections (simple_object_read *sobj, 190 int (*pfn) (void *, const char *, off_t, off_t), 191 void *data, 192 int *err) 193 { 194 return sobj->functions->find_sections (sobj, pfn, data, err); 195 } 196 197 /* Internal data passed to find_one_section. */ 198 199 struct find_one_section_data 200 { 201 /* The section we are looking for. */ 202 const char *name; 203 /* Where to store the section offset. */ 204 off_t *offset; 205 /* Where to store the section length. */ 206 off_t *length; 207 /* Set if the name is found. */ 208 int found; 209 }; 210 211 /* Internal function passed to find_sections. */ 212 213 static int 214 find_one_section (void *data, const char *name, off_t offset, off_t length) 215 { 216 struct find_one_section_data *fosd = (struct find_one_section_data *) data; 217 218 if (strcmp (name, fosd->name) != 0) 219 return 1; 220 221 *fosd->offset = offset; 222 *fosd->length = length; 223 fosd->found = 1; 224 225 /* Stop iteration. */ 226 return 0; 227 } 228 229 /* Find a section. */ 230 231 int 232 simple_object_find_section (simple_object_read *sobj, const char *name, 233 off_t *offset, off_t *length, 234 const char **errmsg, int *err) 235 { 236 struct find_one_section_data fosd; 237 238 fosd.name = name; 239 fosd.offset = offset; 240 fosd.length = length; 241 fosd.found = 0; 242 243 *errmsg = simple_object_find_sections (sobj, find_one_section, 244 (void *) &fosd, err); 245 if (*errmsg != NULL) 246 return 0; 247 if (!fosd.found) 248 return 0; 249 return 1; 250 } 251 252 /* Fetch attributes. */ 253 254 simple_object_attributes * 255 simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg, 256 int *err) 257 { 258 void *data; 259 simple_object_attributes *ret; 260 261 data = sobj->functions->fetch_attributes (sobj, errmsg, err); 262 if (data == NULL) 263 return NULL; 264 ret = XNEW (simple_object_attributes); 265 ret->functions = sobj->functions; 266 ret->data = data; 267 return ret; 268 } 269 270 /* Release an simple_object_read. */ 271 272 void 273 simple_object_release_read (simple_object_read *sobj) 274 { 275 sobj->functions->release_read (sobj->data); 276 XDELETE (sobj); 277 } 278 279 /* Merge attributes. */ 280 281 const char * 282 simple_object_attributes_merge (simple_object_attributes *to, 283 simple_object_attributes *from, 284 int *err) 285 { 286 if (to->functions != from->functions) 287 { 288 *err = 0; 289 return "different object file format"; 290 } 291 return to->functions->attributes_merge (to->data, from->data, err); 292 } 293 294 /* Release an attributes structure. */ 295 296 void 297 simple_object_release_attributes (simple_object_attributes *attrs) 298 { 299 attrs->functions->release_attributes (attrs->data); 300 XDELETE (attrs); 301 } 302 303 /* Start creating an object file. */ 304 305 simple_object_write * 306 simple_object_start_write (simple_object_attributes *attrs, 307 const char *segment_name, const char **errmsg, 308 int *err) 309 { 310 void *data; 311 simple_object_write *ret; 312 313 data = attrs->functions->start_write (attrs->data, errmsg, err); 314 if (data == NULL) 315 return NULL; 316 ret = XNEW (simple_object_write); 317 ret->functions = attrs->functions; 318 ret->segment_name = xstrdup (segment_name); 319 ret->sections = NULL; 320 ret->last_section = NULL; 321 ret->data = data; 322 return ret; 323 } 324 325 /* Start creating a section. */ 326 327 simple_object_write_section * 328 simple_object_write_create_section (simple_object_write *sobj, const char *name, 329 unsigned int align, 330 const char **errmsg ATTRIBUTE_UNUSED, 331 int *err ATTRIBUTE_UNUSED) 332 { 333 simple_object_write_section *ret; 334 335 ret = XNEW (simple_object_write_section); 336 ret->next = NULL; 337 ret->name = xstrdup (name); 338 ret->align = align; 339 ret->buffers = NULL; 340 ret->last_buffer = NULL; 341 342 if (sobj->last_section == NULL) 343 { 344 sobj->sections = ret; 345 sobj->last_section = ret; 346 } 347 else 348 { 349 sobj->last_section->next = ret; 350 sobj->last_section = ret; 351 } 352 353 return ret; 354 } 355 356 /* Add data to a section. */ 357 358 const char * 359 simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED, 360 simple_object_write_section *section, 361 const void *buffer, 362 size_t size, int copy, 363 int *err ATTRIBUTE_UNUSED) 364 { 365 struct simple_object_write_section_buffer *wsb; 366 367 wsb = XNEW (struct simple_object_write_section_buffer); 368 wsb->next = NULL; 369 wsb->size = size; 370 371 if (!copy) 372 { 373 wsb->buffer = buffer; 374 wsb->free_buffer = NULL; 375 } 376 else 377 { 378 wsb->free_buffer = (void *) XNEWVEC (char, size); 379 memcpy (wsb->free_buffer, buffer, size); 380 wsb->buffer = wsb->free_buffer; 381 } 382 383 if (section->last_buffer == NULL) 384 { 385 section->buffers = wsb; 386 section->last_buffer = wsb; 387 } 388 else 389 { 390 section->last_buffer->next = wsb; 391 section->last_buffer = wsb; 392 } 393 394 return NULL; 395 } 396 397 /* Write the complete object file. */ 398 399 const char * 400 simple_object_write_to_file (simple_object_write *sobj, int descriptor, 401 int *err) 402 { 403 return sobj->functions->write_to_file (sobj, descriptor, err); 404 } 405 406 /* Release an simple_object_write. */ 407 408 void 409 simple_object_release_write (simple_object_write *sobj) 410 { 411 simple_object_write_section *section; 412 413 free (sobj->segment_name); 414 415 section = sobj->sections; 416 while (section != NULL) 417 { 418 struct simple_object_write_section_buffer *buffer; 419 simple_object_write_section *next_section; 420 421 buffer = section->buffers; 422 while (buffer != NULL) 423 { 424 struct simple_object_write_section_buffer *next_buffer; 425 426 if (buffer->free_buffer != NULL) 427 XDELETEVEC (buffer->free_buffer); 428 next_buffer = buffer->next; 429 XDELETE (buffer); 430 buffer = next_buffer; 431 } 432 433 next_section = section->next; 434 free (section->name); 435 XDELETE (section); 436 section = next_section; 437 } 438 439 sobj->functions->release_write (sobj->data); 440 XDELETE (sobj); 441 } 442