Annotation of src/external/gpl3/binutils/dist/libiberty/simple-object.c, Revision 1.1.1.3
1.1 christos 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,
1.1.1.3 ! christos 54: &simple_object_coff_functions,
! 55: &simple_object_xcoff_functions
1.1 christos 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:
1.1.1.3 ! christos 73: do
1.1 christos 74: {
1.1.1.3 ! christos 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: }
1.1 christos 89: }
1.1.1.3 ! christos 90: while (size > 0);
1.1 christos 91:
1.1.1.3 ! christos 92: if (size > 0)
1.1 christos 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:
1.1.1.3 ! christos 117: do
1.1 christos 118: {
1.1.1.3 ! christos 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: }
1.1 christos 133: }
1.1.1.3 ! christos 134: while (size > 0);
1.1 christos 135:
1.1.1.3 ! christos 136: if (size > 0)
1.1 christos 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:
1.1.1.2 christos 279: /* Merge attributes. */
1.1 christos 280:
281: const char *
1.1.1.2 christos 282: simple_object_attributes_merge (simple_object_attributes *to,
283: simple_object_attributes *from,
284: int *err)
1.1 christos 285: {
1.1.1.2 christos 286: if (to->functions != from->functions)
1.1 christos 287: {
288: *err = 0;
289: return "different object file format";
290: }
1.1.1.2 christos 291: return to->functions->attributes_merge (to->data, from->data, err);
1.1 christos 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: }
CVSweb <webmaster@jp.NetBSD.org>