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 }; 56 57 /* Read data from a file using the simple_object error reporting 58 conventions. */ 59 60 int 61 simple_object_internal_read (int descriptor, off_t offset, 62 unsigned char *buffer, size_t size, 63 const char **errmsg, int *err) 64 { 65 ssize_t got; 66 67 if (lseek (descriptor, offset, SEEK_SET) < 0) 68 { 69 *errmsg = "lseek"; 70 *err = errno; 71 return 0; 72 } 73 74 got = read (descriptor, buffer, size); 75 if (got < 0) 76 { 77 *errmsg = "read"; 78 *err = errno; 79 return 0; 80 } 81 82 if ((size_t) got < size) 83 { 84 *errmsg = "file too short"; 85 *err = 0; 86 return 0; 87 } 88 89 return 1; 90 } 91 92 /* Write data to a file using the simple_object error reporting 93 conventions. */ 94 95 int 96 simple_object_internal_write (int descriptor, off_t offset, 97 const unsigned char *buffer, size_t size, 98 const char **errmsg, int *err) 99 { 100 ssize_t wrote; 101 102 if (lseek (descriptor, offset, SEEK_SET) < 0) 103 { 104 *errmsg = "lseek"; 105 *err = errno; 106 return 0; 107 } 108 109 wrote = write (descriptor, buffer, size); 110 if (wrote < 0) 111 { 112 *errmsg = "write"; 113 *err = errno; 114 return 0; 115 } 116 117 if ((size_t) wrote < size) 118 { 119 *errmsg = "short write"; 120 *err = 0; 121 return 0; 122 } 123 124 return 1; 125 } 126 127 /* Open for read. */ 128 129 simple_object_read * 130 simple_object_start_read (int descriptor, off_t offset, 131 const char *segment_name, const char **errmsg, 132 int *err) 133 { 134 unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN]; 135 size_t len, i; 136 137 if (!simple_object_internal_read (descriptor, offset, header, 138 SIMPLE_OBJECT_MATCH_HEADER_LEN, 139 errmsg, err)) 140 return NULL; 141 142 len = sizeof (format_functions) / sizeof (format_functions[0]); 143 for (i = 0; i < len; ++i) 144 { 145 void *data; 146 147 data = format_functions[i]->match (header, descriptor, offset, 148 segment_name, errmsg, err); 149 if (data != NULL) 150 { 151 simple_object_read *ret; 152 153 ret = XNEW (simple_object_read); 154 ret->descriptor = descriptor; 155 ret->offset = offset; 156 ret->functions = format_functions[i]; 157 ret->data = data; 158 return ret; 159 } 160 } 161 162 *errmsg = "file not recognized"; 163 *err = 0; 164 return NULL; 165 } 166 167 /* Find all sections. */ 168 169 const char * 170 simple_object_find_sections (simple_object_read *sobj, 171 int (*pfn) (void *, const char *, off_t, off_t), 172 void *data, 173 int *err) 174 { 175 return sobj->functions->find_sections (sobj, pfn, data, err); 176 } 177 178 /* Internal data passed to find_one_section. */ 179 180 struct find_one_section_data 181 { 182 /* The section we are looking for. */ 183 const char *name; 184 /* Where to store the section offset. */ 185 off_t *offset; 186 /* Where to store the section length. */ 187 off_t *length; 188 /* Set if the name is found. */ 189 int found; 190 }; 191 192 /* Internal function passed to find_sections. */ 193 194 static int 195 find_one_section (void *data, const char *name, off_t offset, off_t length) 196 { 197 struct find_one_section_data *fosd = (struct find_one_section_data *) data; 198 199 if (strcmp (name, fosd->name) != 0) 200 return 1; 201 202 *fosd->offset = offset; 203 *fosd->length = length; 204 fosd->found = 1; 205 206 /* Stop iteration. */ 207 return 0; 208 } 209 210 /* Find a section. */ 211 212 int 213 simple_object_find_section (simple_object_read *sobj, const char *name, 214 off_t *offset, off_t *length, 215 const char **errmsg, int *err) 216 { 217 struct find_one_section_data fosd; 218 219 fosd.name = name; 220 fosd.offset = offset; 221 fosd.length = length; 222 fosd.found = 0; 223 224 *errmsg = simple_object_find_sections (sobj, find_one_section, 225 (void *) &fosd, err); 226 if (*errmsg != NULL) 227 return 0; 228 if (!fosd.found) 229 return 0; 230 return 1; 231 } 232 233 /* Fetch attributes. */ 234 235 simple_object_attributes * 236 simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg, 237 int *err) 238 { 239 void *data; 240 simple_object_attributes *ret; 241 242 data = sobj->functions->fetch_attributes (sobj, errmsg, err); 243 if (data == NULL) 244 return NULL; 245 ret = XNEW (simple_object_attributes); 246 ret->functions = sobj->functions; 247 ret->data = data; 248 return ret; 249 } 250 251 /* Release an simple_object_read. */ 252 253 void 254 simple_object_release_read (simple_object_read *sobj) 255 { 256 sobj->functions->release_read (sobj->data); 257 XDELETE (sobj); 258 } 259 260 /* Compare attributes. */ 261 262 const char * 263 simple_object_attributes_compare (simple_object_attributes *attrs1, 264 simple_object_attributes *attrs2, 265 int *err) 266 { 267 if (attrs1->functions != attrs2->functions) 268 { 269 *err = 0; 270 return "different object file format"; 271 } 272 return attrs1->functions->attributes_compare (attrs1->data, attrs2->data, 273 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