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 5This program is free software; you can redistribute it and/or modify it 6under the terms of the GNU General Public License as published by the 7Free Software Foundation; either version 2, or (at your option) any 8later version. 9 10This program is distributed in the hope that it will be useful, 11but WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 51 Franklin Street - Fifth Floor, 18Boston, 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 50static 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 61int 62simple_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 105int 106simple_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 148simple_object_read * 149simple_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 188const char * 189simple_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 199struct 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 213static int 214find_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 231int 232simple_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 254simple_object_attributes * 255simple_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 272void 273simple_object_release_read (simple_object_read *sobj) 274{ 275 sobj->functions->release_read (sobj->data); 276 XDELETE (sobj); 277} 278 279/* Merge attributes. */ 280 281const char * 282simple_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 296void 297simple_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 305simple_object_write * 306simple_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 327simple_object_write_section * 328simple_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 358const char * 359simple_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 399const char * 400simple_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 408void 409simple_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