1*a9fa9459Szrj /* simple-object.c -- simple routines to read and write object files.
2*a9fa9459Szrj Copyright 2010 Free Software Foundation, Inc.
3*a9fa9459Szrj Written by Ian Lance Taylor, Google.
4*a9fa9459Szrj
5*a9fa9459Szrj This program is free software; you can redistribute it and/or modify it
6*a9fa9459Szrj under the terms of the GNU General Public License as published by the
7*a9fa9459Szrj Free Software Foundation; either version 2, or (at your option) any
8*a9fa9459Szrj later version.
9*a9fa9459Szrj
10*a9fa9459Szrj This program is distributed in the hope that it will be useful,
11*a9fa9459Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
12*a9fa9459Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*a9fa9459Szrj GNU General Public License for more details.
14*a9fa9459Szrj
15*a9fa9459Szrj You should have received a copy of the GNU General Public License
16*a9fa9459Szrj along with this program; if not, write to the Free Software
17*a9fa9459Szrj Foundation, 51 Franklin Street - Fifth Floor,
18*a9fa9459Szrj Boston, MA 02110-1301, USA. */
19*a9fa9459Szrj
20*a9fa9459Szrj #include "config.h"
21*a9fa9459Szrj #include "libiberty.h"
22*a9fa9459Szrj #include "simple-object.h"
23*a9fa9459Szrj
24*a9fa9459Szrj #include <errno.h>
25*a9fa9459Szrj
26*a9fa9459Szrj #ifdef HAVE_STDLIB_H
27*a9fa9459Szrj #include <stdlib.h>
28*a9fa9459Szrj #endif
29*a9fa9459Szrj
30*a9fa9459Szrj #ifdef HAVE_STDINT_H
31*a9fa9459Szrj #include <stdint.h>
32*a9fa9459Szrj #endif
33*a9fa9459Szrj
34*a9fa9459Szrj #ifdef HAVE_STRING_H
35*a9fa9459Szrj #include <string.h>
36*a9fa9459Szrj #endif
37*a9fa9459Szrj
38*a9fa9459Szrj #ifdef HAVE_INTTYPES_H
39*a9fa9459Szrj #include <inttypes.h>
40*a9fa9459Szrj #endif
41*a9fa9459Szrj
42*a9fa9459Szrj #ifndef SEEK_SET
43*a9fa9459Szrj #define SEEK_SET 0
44*a9fa9459Szrj #endif
45*a9fa9459Szrj
46*a9fa9459Szrj #include "simple-object-common.h"
47*a9fa9459Szrj
48*a9fa9459Szrj /* The known object file formats. */
49*a9fa9459Szrj
50*a9fa9459Szrj static const struct simple_object_functions * const format_functions[] =
51*a9fa9459Szrj {
52*a9fa9459Szrj &simple_object_elf_functions,
53*a9fa9459Szrj &simple_object_mach_o_functions,
54*a9fa9459Szrj &simple_object_coff_functions,
55*a9fa9459Szrj &simple_object_xcoff_functions
56*a9fa9459Szrj };
57*a9fa9459Szrj
58*a9fa9459Szrj /* Read data from a file using the simple_object error reporting
59*a9fa9459Szrj conventions. */
60*a9fa9459Szrj
61*a9fa9459Szrj int
simple_object_internal_read(int descriptor,off_t offset,unsigned char * buffer,size_t size,const char ** errmsg,int * err)62*a9fa9459Szrj simple_object_internal_read (int descriptor, off_t offset,
63*a9fa9459Szrj unsigned char *buffer, size_t size,
64*a9fa9459Szrj const char **errmsg, int *err)
65*a9fa9459Szrj {
66*a9fa9459Szrj if (lseek (descriptor, offset, SEEK_SET) < 0)
67*a9fa9459Szrj {
68*a9fa9459Szrj *errmsg = "lseek";
69*a9fa9459Szrj *err = errno;
70*a9fa9459Szrj return 0;
71*a9fa9459Szrj }
72*a9fa9459Szrj
73*a9fa9459Szrj do
74*a9fa9459Szrj {
75*a9fa9459Szrj ssize_t got = read (descriptor, buffer, size);
76*a9fa9459Szrj if (got == 0)
77*a9fa9459Szrj break;
78*a9fa9459Szrj else if (got > 0)
79*a9fa9459Szrj {
80*a9fa9459Szrj buffer += got;
81*a9fa9459Szrj size -= got;
82*a9fa9459Szrj }
83*a9fa9459Szrj else if (errno != EINTR)
84*a9fa9459Szrj {
85*a9fa9459Szrj *errmsg = "read";
86*a9fa9459Szrj *err = errno;
87*a9fa9459Szrj return 0;
88*a9fa9459Szrj }
89*a9fa9459Szrj }
90*a9fa9459Szrj while (size > 0);
91*a9fa9459Szrj
92*a9fa9459Szrj if (size > 0)
93*a9fa9459Szrj {
94*a9fa9459Szrj *errmsg = "file too short";
95*a9fa9459Szrj *err = 0;
96*a9fa9459Szrj return 0;
97*a9fa9459Szrj }
98*a9fa9459Szrj
99*a9fa9459Szrj return 1;
100*a9fa9459Szrj }
101*a9fa9459Szrj
102*a9fa9459Szrj /* Write data to a file using the simple_object error reporting
103*a9fa9459Szrj conventions. */
104*a9fa9459Szrj
105*a9fa9459Szrj int
simple_object_internal_write(int descriptor,off_t offset,const unsigned char * buffer,size_t size,const char ** errmsg,int * err)106*a9fa9459Szrj simple_object_internal_write (int descriptor, off_t offset,
107*a9fa9459Szrj const unsigned char *buffer, size_t size,
108*a9fa9459Szrj const char **errmsg, int *err)
109*a9fa9459Szrj {
110*a9fa9459Szrj if (lseek (descriptor, offset, SEEK_SET) < 0)
111*a9fa9459Szrj {
112*a9fa9459Szrj *errmsg = "lseek";
113*a9fa9459Szrj *err = errno;
114*a9fa9459Szrj return 0;
115*a9fa9459Szrj }
116*a9fa9459Szrj
117*a9fa9459Szrj do
118*a9fa9459Szrj {
119*a9fa9459Szrj ssize_t wrote = write (descriptor, buffer, size);
120*a9fa9459Szrj if (wrote == 0)
121*a9fa9459Szrj break;
122*a9fa9459Szrj else if (wrote > 0)
123*a9fa9459Szrj {
124*a9fa9459Szrj buffer += wrote;
125*a9fa9459Szrj size -= wrote;
126*a9fa9459Szrj }
127*a9fa9459Szrj else if (errno != EINTR)
128*a9fa9459Szrj {
129*a9fa9459Szrj *errmsg = "write";
130*a9fa9459Szrj *err = errno;
131*a9fa9459Szrj return 0;
132*a9fa9459Szrj }
133*a9fa9459Szrj }
134*a9fa9459Szrj while (size > 0);
135*a9fa9459Szrj
136*a9fa9459Szrj if (size > 0)
137*a9fa9459Szrj {
138*a9fa9459Szrj *errmsg = "short write";
139*a9fa9459Szrj *err = 0;
140*a9fa9459Szrj return 0;
141*a9fa9459Szrj }
142*a9fa9459Szrj
143*a9fa9459Szrj return 1;
144*a9fa9459Szrj }
145*a9fa9459Szrj
146*a9fa9459Szrj /* Open for read. */
147*a9fa9459Szrj
148*a9fa9459Szrj simple_object_read *
simple_object_start_read(int descriptor,off_t offset,const char * segment_name,const char ** errmsg,int * err)149*a9fa9459Szrj simple_object_start_read (int descriptor, off_t offset,
150*a9fa9459Szrj const char *segment_name, const char **errmsg,
151*a9fa9459Szrj int *err)
152*a9fa9459Szrj {
153*a9fa9459Szrj unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
154*a9fa9459Szrj size_t len, i;
155*a9fa9459Szrj
156*a9fa9459Szrj if (!simple_object_internal_read (descriptor, offset, header,
157*a9fa9459Szrj SIMPLE_OBJECT_MATCH_HEADER_LEN,
158*a9fa9459Szrj errmsg, err))
159*a9fa9459Szrj return NULL;
160*a9fa9459Szrj
161*a9fa9459Szrj len = sizeof (format_functions) / sizeof (format_functions[0]);
162*a9fa9459Szrj for (i = 0; i < len; ++i)
163*a9fa9459Szrj {
164*a9fa9459Szrj void *data;
165*a9fa9459Szrj
166*a9fa9459Szrj data = format_functions[i]->match (header, descriptor, offset,
167*a9fa9459Szrj segment_name, errmsg, err);
168*a9fa9459Szrj if (data != NULL)
169*a9fa9459Szrj {
170*a9fa9459Szrj simple_object_read *ret;
171*a9fa9459Szrj
172*a9fa9459Szrj ret = XNEW (simple_object_read);
173*a9fa9459Szrj ret->descriptor = descriptor;
174*a9fa9459Szrj ret->offset = offset;
175*a9fa9459Szrj ret->functions = format_functions[i];
176*a9fa9459Szrj ret->data = data;
177*a9fa9459Szrj return ret;
178*a9fa9459Szrj }
179*a9fa9459Szrj }
180*a9fa9459Szrj
181*a9fa9459Szrj *errmsg = "file not recognized";
182*a9fa9459Szrj *err = 0;
183*a9fa9459Szrj return NULL;
184*a9fa9459Szrj }
185*a9fa9459Szrj
186*a9fa9459Szrj /* Find all sections. */
187*a9fa9459Szrj
188*a9fa9459Szrj const char *
simple_object_find_sections(simple_object_read * sobj,int (* pfn)(void *,const char *,off_t,off_t),void * data,int * err)189*a9fa9459Szrj simple_object_find_sections (simple_object_read *sobj,
190*a9fa9459Szrj int (*pfn) (void *, const char *, off_t, off_t),
191*a9fa9459Szrj void *data,
192*a9fa9459Szrj int *err)
193*a9fa9459Szrj {
194*a9fa9459Szrj return sobj->functions->find_sections (sobj, pfn, data, err);
195*a9fa9459Szrj }
196*a9fa9459Szrj
197*a9fa9459Szrj /* Internal data passed to find_one_section. */
198*a9fa9459Szrj
199*a9fa9459Szrj struct find_one_section_data
200*a9fa9459Szrj {
201*a9fa9459Szrj /* The section we are looking for. */
202*a9fa9459Szrj const char *name;
203*a9fa9459Szrj /* Where to store the section offset. */
204*a9fa9459Szrj off_t *offset;
205*a9fa9459Szrj /* Where to store the section length. */
206*a9fa9459Szrj off_t *length;
207*a9fa9459Szrj /* Set if the name is found. */
208*a9fa9459Szrj int found;
209*a9fa9459Szrj };
210*a9fa9459Szrj
211*a9fa9459Szrj /* Internal function passed to find_sections. */
212*a9fa9459Szrj
213*a9fa9459Szrj static int
find_one_section(void * data,const char * name,off_t offset,off_t length)214*a9fa9459Szrj find_one_section (void *data, const char *name, off_t offset, off_t length)
215*a9fa9459Szrj {
216*a9fa9459Szrj struct find_one_section_data *fosd = (struct find_one_section_data *) data;
217*a9fa9459Szrj
218*a9fa9459Szrj if (strcmp (name, fosd->name) != 0)
219*a9fa9459Szrj return 1;
220*a9fa9459Szrj
221*a9fa9459Szrj *fosd->offset = offset;
222*a9fa9459Szrj *fosd->length = length;
223*a9fa9459Szrj fosd->found = 1;
224*a9fa9459Szrj
225*a9fa9459Szrj /* Stop iteration. */
226*a9fa9459Szrj return 0;
227*a9fa9459Szrj }
228*a9fa9459Szrj
229*a9fa9459Szrj /* Find a section. */
230*a9fa9459Szrj
231*a9fa9459Szrj int
simple_object_find_section(simple_object_read * sobj,const char * name,off_t * offset,off_t * length,const char ** errmsg,int * err)232*a9fa9459Szrj simple_object_find_section (simple_object_read *sobj, const char *name,
233*a9fa9459Szrj off_t *offset, off_t *length,
234*a9fa9459Szrj const char **errmsg, int *err)
235*a9fa9459Szrj {
236*a9fa9459Szrj struct find_one_section_data fosd;
237*a9fa9459Szrj
238*a9fa9459Szrj fosd.name = name;
239*a9fa9459Szrj fosd.offset = offset;
240*a9fa9459Szrj fosd.length = length;
241*a9fa9459Szrj fosd.found = 0;
242*a9fa9459Szrj
243*a9fa9459Szrj *errmsg = simple_object_find_sections (sobj, find_one_section,
244*a9fa9459Szrj (void *) &fosd, err);
245*a9fa9459Szrj if (*errmsg != NULL)
246*a9fa9459Szrj return 0;
247*a9fa9459Szrj if (!fosd.found)
248*a9fa9459Szrj return 0;
249*a9fa9459Szrj return 1;
250*a9fa9459Szrj }
251*a9fa9459Szrj
252*a9fa9459Szrj /* Fetch attributes. */
253*a9fa9459Szrj
254*a9fa9459Szrj simple_object_attributes *
simple_object_fetch_attributes(simple_object_read * sobj,const char ** errmsg,int * err)255*a9fa9459Szrj simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
256*a9fa9459Szrj int *err)
257*a9fa9459Szrj {
258*a9fa9459Szrj void *data;
259*a9fa9459Szrj simple_object_attributes *ret;
260*a9fa9459Szrj
261*a9fa9459Szrj data = sobj->functions->fetch_attributes (sobj, errmsg, err);
262*a9fa9459Szrj if (data == NULL)
263*a9fa9459Szrj return NULL;
264*a9fa9459Szrj ret = XNEW (simple_object_attributes);
265*a9fa9459Szrj ret->functions = sobj->functions;
266*a9fa9459Szrj ret->data = data;
267*a9fa9459Szrj return ret;
268*a9fa9459Szrj }
269*a9fa9459Szrj
270*a9fa9459Szrj /* Release an simple_object_read. */
271*a9fa9459Szrj
272*a9fa9459Szrj void
simple_object_release_read(simple_object_read * sobj)273*a9fa9459Szrj simple_object_release_read (simple_object_read *sobj)
274*a9fa9459Szrj {
275*a9fa9459Szrj sobj->functions->release_read (sobj->data);
276*a9fa9459Szrj XDELETE (sobj);
277*a9fa9459Szrj }
278*a9fa9459Szrj
279*a9fa9459Szrj /* Merge attributes. */
280*a9fa9459Szrj
281*a9fa9459Szrj const char *
simple_object_attributes_merge(simple_object_attributes * to,simple_object_attributes * from,int * err)282*a9fa9459Szrj simple_object_attributes_merge (simple_object_attributes *to,
283*a9fa9459Szrj simple_object_attributes *from,
284*a9fa9459Szrj int *err)
285*a9fa9459Szrj {
286*a9fa9459Szrj if (to->functions != from->functions)
287*a9fa9459Szrj {
288*a9fa9459Szrj *err = 0;
289*a9fa9459Szrj return "different object file format";
290*a9fa9459Szrj }
291*a9fa9459Szrj return to->functions->attributes_merge (to->data, from->data, err);
292*a9fa9459Szrj }
293*a9fa9459Szrj
294*a9fa9459Szrj /* Release an attributes structure. */
295*a9fa9459Szrj
296*a9fa9459Szrj void
simple_object_release_attributes(simple_object_attributes * attrs)297*a9fa9459Szrj simple_object_release_attributes (simple_object_attributes *attrs)
298*a9fa9459Szrj {
299*a9fa9459Szrj attrs->functions->release_attributes (attrs->data);
300*a9fa9459Szrj XDELETE (attrs);
301*a9fa9459Szrj }
302*a9fa9459Szrj
303*a9fa9459Szrj /* Start creating an object file. */
304*a9fa9459Szrj
305*a9fa9459Szrj simple_object_write *
simple_object_start_write(simple_object_attributes * attrs,const char * segment_name,const char ** errmsg,int * err)306*a9fa9459Szrj simple_object_start_write (simple_object_attributes *attrs,
307*a9fa9459Szrj const char *segment_name, const char **errmsg,
308*a9fa9459Szrj int *err)
309*a9fa9459Szrj {
310*a9fa9459Szrj void *data;
311*a9fa9459Szrj simple_object_write *ret;
312*a9fa9459Szrj
313*a9fa9459Szrj data = attrs->functions->start_write (attrs->data, errmsg, err);
314*a9fa9459Szrj if (data == NULL)
315*a9fa9459Szrj return NULL;
316*a9fa9459Szrj ret = XNEW (simple_object_write);
317*a9fa9459Szrj ret->functions = attrs->functions;
318*a9fa9459Szrj ret->segment_name = xstrdup (segment_name);
319*a9fa9459Szrj ret->sections = NULL;
320*a9fa9459Szrj ret->last_section = NULL;
321*a9fa9459Szrj ret->data = data;
322*a9fa9459Szrj return ret;
323*a9fa9459Szrj }
324*a9fa9459Szrj
325*a9fa9459Szrj /* Start creating a section. */
326*a9fa9459Szrj
327*a9fa9459Szrj simple_object_write_section *
simple_object_write_create_section(simple_object_write * sobj,const char * name,unsigned int align,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)328*a9fa9459Szrj simple_object_write_create_section (simple_object_write *sobj, const char *name,
329*a9fa9459Szrj unsigned int align,
330*a9fa9459Szrj const char **errmsg ATTRIBUTE_UNUSED,
331*a9fa9459Szrj int *err ATTRIBUTE_UNUSED)
332*a9fa9459Szrj {
333*a9fa9459Szrj simple_object_write_section *ret;
334*a9fa9459Szrj
335*a9fa9459Szrj ret = XNEW (simple_object_write_section);
336*a9fa9459Szrj ret->next = NULL;
337*a9fa9459Szrj ret->name = xstrdup (name);
338*a9fa9459Szrj ret->align = align;
339*a9fa9459Szrj ret->buffers = NULL;
340*a9fa9459Szrj ret->last_buffer = NULL;
341*a9fa9459Szrj
342*a9fa9459Szrj if (sobj->last_section == NULL)
343*a9fa9459Szrj {
344*a9fa9459Szrj sobj->sections = ret;
345*a9fa9459Szrj sobj->last_section = ret;
346*a9fa9459Szrj }
347*a9fa9459Szrj else
348*a9fa9459Szrj {
349*a9fa9459Szrj sobj->last_section->next = ret;
350*a9fa9459Szrj sobj->last_section = ret;
351*a9fa9459Szrj }
352*a9fa9459Szrj
353*a9fa9459Szrj return ret;
354*a9fa9459Szrj }
355*a9fa9459Szrj
356*a9fa9459Szrj /* Add data to a section. */
357*a9fa9459Szrj
358*a9fa9459Szrj const char *
simple_object_write_add_data(simple_object_write * sobj ATTRIBUTE_UNUSED,simple_object_write_section * section,const void * buffer,size_t size,int copy,int * err ATTRIBUTE_UNUSED)359*a9fa9459Szrj simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
360*a9fa9459Szrj simple_object_write_section *section,
361*a9fa9459Szrj const void *buffer,
362*a9fa9459Szrj size_t size, int copy,
363*a9fa9459Szrj int *err ATTRIBUTE_UNUSED)
364*a9fa9459Szrj {
365*a9fa9459Szrj struct simple_object_write_section_buffer *wsb;
366*a9fa9459Szrj
367*a9fa9459Szrj wsb = XNEW (struct simple_object_write_section_buffer);
368*a9fa9459Szrj wsb->next = NULL;
369*a9fa9459Szrj wsb->size = size;
370*a9fa9459Szrj
371*a9fa9459Szrj if (!copy)
372*a9fa9459Szrj {
373*a9fa9459Szrj wsb->buffer = buffer;
374*a9fa9459Szrj wsb->free_buffer = NULL;
375*a9fa9459Szrj }
376*a9fa9459Szrj else
377*a9fa9459Szrj {
378*a9fa9459Szrj wsb->free_buffer = (void *) XNEWVEC (char, size);
379*a9fa9459Szrj memcpy (wsb->free_buffer, buffer, size);
380*a9fa9459Szrj wsb->buffer = wsb->free_buffer;
381*a9fa9459Szrj }
382*a9fa9459Szrj
383*a9fa9459Szrj if (section->last_buffer == NULL)
384*a9fa9459Szrj {
385*a9fa9459Szrj section->buffers = wsb;
386*a9fa9459Szrj section->last_buffer = wsb;
387*a9fa9459Szrj }
388*a9fa9459Szrj else
389*a9fa9459Szrj {
390*a9fa9459Szrj section->last_buffer->next = wsb;
391*a9fa9459Szrj section->last_buffer = wsb;
392*a9fa9459Szrj }
393*a9fa9459Szrj
394*a9fa9459Szrj return NULL;
395*a9fa9459Szrj }
396*a9fa9459Szrj
397*a9fa9459Szrj /* Write the complete object file. */
398*a9fa9459Szrj
399*a9fa9459Szrj const char *
simple_object_write_to_file(simple_object_write * sobj,int descriptor,int * err)400*a9fa9459Szrj simple_object_write_to_file (simple_object_write *sobj, int descriptor,
401*a9fa9459Szrj int *err)
402*a9fa9459Szrj {
403*a9fa9459Szrj return sobj->functions->write_to_file (sobj, descriptor, err);
404*a9fa9459Szrj }
405*a9fa9459Szrj
406*a9fa9459Szrj /* Release an simple_object_write. */
407*a9fa9459Szrj
408*a9fa9459Szrj void
simple_object_release_write(simple_object_write * sobj)409*a9fa9459Szrj simple_object_release_write (simple_object_write *sobj)
410*a9fa9459Szrj {
411*a9fa9459Szrj simple_object_write_section *section;
412*a9fa9459Szrj
413*a9fa9459Szrj free (sobj->segment_name);
414*a9fa9459Szrj
415*a9fa9459Szrj section = sobj->sections;
416*a9fa9459Szrj while (section != NULL)
417*a9fa9459Szrj {
418*a9fa9459Szrj struct simple_object_write_section_buffer *buffer;
419*a9fa9459Szrj simple_object_write_section *next_section;
420*a9fa9459Szrj
421*a9fa9459Szrj buffer = section->buffers;
422*a9fa9459Szrj while (buffer != NULL)
423*a9fa9459Szrj {
424*a9fa9459Szrj struct simple_object_write_section_buffer *next_buffer;
425*a9fa9459Szrj
426*a9fa9459Szrj if (buffer->free_buffer != NULL)
427*a9fa9459Szrj XDELETEVEC (buffer->free_buffer);
428*a9fa9459Szrj next_buffer = buffer->next;
429*a9fa9459Szrj XDELETE (buffer);
430*a9fa9459Szrj buffer = next_buffer;
431*a9fa9459Szrj }
432*a9fa9459Szrj
433*a9fa9459Szrj next_section = section->next;
434*a9fa9459Szrj free (section->name);
435*a9fa9459Szrj XDELETE (section);
436*a9fa9459Szrj section = next_section;
437*a9fa9459Szrj }
438*a9fa9459Szrj
439*a9fa9459Szrj sobj->functions->release_write (sobj->data);
440*a9fa9459Szrj XDELETE (sobj);
441*a9fa9459Szrj }
442