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.
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
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.
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. */
21 #include "libiberty.h"
22 #include "simple-object.h"
38 #ifdef HAVE_INTTYPES_H
46 #include "simple-object-common.h"
48 /* The known object file formats. */
50 static const struct simple_object_functions
* const format_functions
[] =
52 &simple_object_elf_functions
,
53 &simple_object_mach_o_functions
,
54 &simple_object_coff_functions
,
55 &simple_object_xcoff_functions
58 /* Read data from a file using the simple_object error reporting
62 simple_object_internal_read (int descriptor
, off_t offset
,
63 unsigned char *buffer
, size_t size
,
64 const char **errmsg
, int *err
)
66 if (lseek (descriptor
, offset
, SEEK_SET
) < 0)
75 ssize_t got
= read (descriptor
, buffer
, size
);
83 else if (errno
!= EINTR
)
94 *errmsg
= "file too short";
102 /* Write data to a file using the simple_object error reporting
106 simple_object_internal_write (int descriptor
, off_t offset
,
107 const unsigned char *buffer
, size_t size
,
108 const char **errmsg
, int *err
)
112 if (lseek (descriptor
, offset
, SEEK_SET
) < 0)
119 wrote
= write (descriptor
, buffer
, size
);
127 if ((size_t) wrote
< size
)
129 *errmsg
= "short write";
140 simple_object_start_read (int descriptor
, off_t offset
,
141 const char *segment_name
, const char **errmsg
,
144 unsigned char header
[SIMPLE_OBJECT_MATCH_HEADER_LEN
];
147 if (!simple_object_internal_read (descriptor
, offset
, header
,
148 SIMPLE_OBJECT_MATCH_HEADER_LEN
,
152 len
= sizeof (format_functions
) / sizeof (format_functions
[0]);
153 for (i
= 0; i
< len
; ++i
)
157 data
= format_functions
[i
]->match (header
, descriptor
, offset
,
158 segment_name
, errmsg
, err
);
161 simple_object_read
*ret
;
163 ret
= XNEW (simple_object_read
);
164 ret
->descriptor
= descriptor
;
165 ret
->offset
= offset
;
166 ret
->functions
= format_functions
[i
];
172 *errmsg
= "file not recognized";
177 /* Find all sections. */
180 simple_object_find_sections (simple_object_read
*sobj
,
181 int (*pfn
) (void *, const char *, off_t
, off_t
),
185 return sobj
->functions
->find_sections (sobj
, pfn
, data
, err
);
188 /* Internal data passed to find_one_section. */
190 struct find_one_section_data
192 /* The section we are looking for. */
194 /* Where to store the section offset. */
196 /* Where to store the section length. */
198 /* Set if the name is found. */
202 /* Internal function passed to find_sections. */
205 find_one_section (void *data
, const char *name
, off_t offset
, off_t length
)
207 struct find_one_section_data
*fosd
= (struct find_one_section_data
*) data
;
209 if (strcmp (name
, fosd
->name
) != 0)
212 *fosd
->offset
= offset
;
213 *fosd
->length
= length
;
216 /* Stop iteration. */
220 /* Find a section. */
223 simple_object_find_section (simple_object_read
*sobj
, const char *name
,
224 off_t
*offset
, off_t
*length
,
225 const char **errmsg
, int *err
)
227 struct find_one_section_data fosd
;
230 fosd
.offset
= offset
;
231 fosd
.length
= length
;
234 *errmsg
= simple_object_find_sections (sobj
, find_one_section
,
235 (void *) &fosd
, err
);
243 /* Fetch attributes. */
245 simple_object_attributes
*
246 simple_object_fetch_attributes (simple_object_read
*sobj
, const char **errmsg
,
250 simple_object_attributes
*ret
;
252 data
= sobj
->functions
->fetch_attributes (sobj
, errmsg
, err
);
255 ret
= XNEW (simple_object_attributes
);
256 ret
->functions
= sobj
->functions
;
261 /* Release an simple_object_read. */
264 simple_object_release_read (simple_object_read
*sobj
)
266 sobj
->functions
->release_read (sobj
->data
);
270 /* Merge attributes. */
273 simple_object_attributes_merge (simple_object_attributes
*to
,
274 simple_object_attributes
*from
,
277 if (to
->functions
!= from
->functions
)
280 return "different object file format";
282 return to
->functions
->attributes_merge (to
->data
, from
->data
, err
);
285 /* Release an attributes structure. */
288 simple_object_release_attributes (simple_object_attributes
*attrs
)
290 attrs
->functions
->release_attributes (attrs
->data
);
294 /* Start creating an object file. */
296 simple_object_write
*
297 simple_object_start_write (simple_object_attributes
*attrs
,
298 const char *segment_name
, const char **errmsg
,
302 simple_object_write
*ret
;
304 data
= attrs
->functions
->start_write (attrs
->data
, errmsg
, err
);
307 ret
= XNEW (simple_object_write
);
308 ret
->functions
= attrs
->functions
;
309 ret
->segment_name
= xstrdup (segment_name
);
310 ret
->sections
= NULL
;
311 ret
->last_section
= NULL
;
316 /* Start creating a section. */
318 simple_object_write_section
*
319 simple_object_write_create_section (simple_object_write
*sobj
, const char *name
,
321 const char **errmsg ATTRIBUTE_UNUSED
,
322 int *err ATTRIBUTE_UNUSED
)
324 simple_object_write_section
*ret
;
326 ret
= XNEW (simple_object_write_section
);
328 ret
->name
= xstrdup (name
);
331 ret
->last_buffer
= NULL
;
333 if (sobj
->last_section
== NULL
)
335 sobj
->sections
= ret
;
336 sobj
->last_section
= ret
;
340 sobj
->last_section
->next
= ret
;
341 sobj
->last_section
= ret
;
347 /* Add data to a section. */
350 simple_object_write_add_data (simple_object_write
*sobj ATTRIBUTE_UNUSED
,
351 simple_object_write_section
*section
,
353 size_t size
, int copy
,
354 int *err ATTRIBUTE_UNUSED
)
356 struct simple_object_write_section_buffer
*wsb
;
358 wsb
= XNEW (struct simple_object_write_section_buffer
);
364 wsb
->buffer
= buffer
;
365 wsb
->free_buffer
= NULL
;
369 wsb
->free_buffer
= (void *) XNEWVEC (char, size
);
370 memcpy (wsb
->free_buffer
, buffer
, size
);
371 wsb
->buffer
= wsb
->free_buffer
;
374 if (section
->last_buffer
== NULL
)
376 section
->buffers
= wsb
;
377 section
->last_buffer
= wsb
;
381 section
->last_buffer
->next
= wsb
;
382 section
->last_buffer
= wsb
;
388 /* Write the complete object file. */
391 simple_object_write_to_file (simple_object_write
*sobj
, int descriptor
,
394 return sobj
->functions
->write_to_file (sobj
, descriptor
, err
);
397 /* Release an simple_object_write. */
400 simple_object_release_write (simple_object_write
*sobj
)
402 simple_object_write_section
*section
;
404 free (sobj
->segment_name
);
406 section
= sobj
->sections
;
407 while (section
!= NULL
)
409 struct simple_object_write_section_buffer
*buffer
;
410 simple_object_write_section
*next_section
;
412 buffer
= section
->buffers
;
413 while (buffer
!= NULL
)
415 struct simple_object_write_section_buffer
*next_buffer
;
417 if (buffer
->free_buffer
!= NULL
)
418 XDELETEVEC (buffer
->free_buffer
);
419 next_buffer
= buffer
->next
;
421 buffer
= next_buffer
;
424 next_section
= section
->next
;
425 free (section
->name
);
427 section
= next_section
;
430 sobj
->functions
->release_write (sobj
->data
);