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 /* Merge attributes. */ 261 262 const char * 263 simple_object_attributes_merge (simple_object_attributes *to, 264 simple_object_attributes *from, 265 int *err) 266 { 267 if (to->functions != from->functions) 268 { 269 *err = 0; 270 return "different object file format"; 271 } 272 return to->functions->attributes_merge (to->data, from->data, err); 273 } 274 275 /* Release an attributes structure. */ 276 277 void 278 simple_object_release_attributes (simple_object_attributes *attrs) 279 { 280 attrs->functions->release_attributes (attrs->data); 281 XDELETE (attrs); 282 } 283 284 /* Start creating an object file. */ 285 286 simple_object_write * 287 simple_object_start_write (simple_object_attributes *attrs, 288 const char *segment_name, const char **errmsg, 289 int *err) 290 { 291 void *data; 292 simple_object_write *ret; 293 294 data = attrs->functions->start_write (attrs->data, errmsg, err); 295 if (data == NULL) 296 return NULL; 297 ret = XNEW (simple_object_write); 298 ret->functions = attrs->functions; 299 ret->segment_name = xstrdup (segment_name); 300 ret->sections = NULL; 301 ret->last_section = NULL; 302 ret->data = data; 303 return ret; 304 } 305 306 /* Start creating a section. */ 307 308 simple_object_write_section * 309 simple_object_write_create_section (simple_object_write *sobj, const char *name, 310 unsigned int align, 311 const char **errmsg ATTRIBUTE_UNUSED, 312 int *err ATTRIBUTE_UNUSED) 313 { 314 simple_object_write_section *ret; 315 316 ret = XNEW (simple_object_write_section); 317 ret->next = NULL; 318 ret->name = xstrdup (name); 319 ret->align = align; 320 ret->buffers = NULL; 321 ret->last_buffer = NULL; 322 323 if (sobj->last_section == NULL) 324 { 325 sobj->sections = ret; 326 sobj->last_section = ret; 327 } 328 else 329 { 330 sobj->last_section->next = ret; 331 sobj->last_section = ret; 332 } 333 334 return ret; 335 } 336 337 /* Add data to a section. */ 338 339 const char * 340 simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED, 341 simple_object_write_section *section, 342 const void *buffer, 343 size_t size, int copy, 344 int *err ATTRIBUTE_UNUSED) 345 { 346 struct simple_object_write_section_buffer *wsb; 347 348 wsb = XNEW (struct simple_object_write_section_buffer); 349 wsb->next = NULL; 350 wsb->size = size; 351 352 if (!copy) 353 { 354 wsb->buffer = buffer; 355 wsb->free_buffer = NULL; 356 } 357 else 358 { 359 wsb->free_buffer = (void *) XNEWVEC (char, size); 360 memcpy (wsb->free_buffer, buffer, size); 361 wsb->buffer = wsb->free_buffer; 362 } 363 364 if (section->last_buffer == NULL) 365 { 366 section->buffers = wsb; 367 section->last_buffer = wsb; 368 } 369 else 370 { 371 section->last_buffer->next = wsb; 372 section->last_buffer = wsb; 373 } 374 375 return NULL; 376 } 377 378 /* Write the complete object file. */ 379 380 const char * 381 simple_object_write_to_file (simple_object_write *sobj, int descriptor, 382 int *err) 383 { 384 return sobj->functions->write_to_file (sobj, descriptor, err); 385 } 386 387 /* Release an simple_object_write. */ 388 389 void 390 simple_object_release_write (simple_object_write *sobj) 391 { 392 simple_object_write_section *section; 393 394 free (sobj->segment_name); 395 396 section = sobj->sections; 397 while (section != NULL) 398 { 399 struct simple_object_write_section_buffer *buffer; 400 simple_object_write_section *next_section; 401 402 buffer = section->buffers; 403 while (buffer != NULL) 404 { 405 struct simple_object_write_section_buffer *next_buffer; 406 407 if (buffer->free_buffer != NULL) 408 XDELETEVEC (buffer->free_buffer); 409 next_buffer = buffer->next; 410 XDELETE (buffer); 411 buffer = next_buffer; 412 } 413 414 next_section = section->next; 415 free (section->name); 416 XDELETE (section); 417 section = next_section; 418 } 419 420 sobj->functions->release_write (sobj->data); 421 XDELETE (sobj); 422 } 423