simple-object.c revision 1.1
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
5This program is free software; you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option) any
8later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 51 Franklin Street - Fifth Floor,
18Boston, 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
50static 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  &simple_object_xcoff_functions
56};
57
58/* Read data from a file using the simple_object error reporting
59   conventions.  */
60
61int
62simple_object_internal_read (int descriptor, off_t offset,
63			     unsigned char *buffer, size_t size,
64			     const char **errmsg, int *err)
65{
66  ssize_t got;
67
68  if (lseek (descriptor, offset, SEEK_SET) < 0)
69    {
70      *errmsg = "lseek";
71      *err = errno;
72      return 0;
73    }
74
75  got = read (descriptor, buffer, size);
76  if (got < 0)
77    {
78      *errmsg = "read";
79      *err = errno;
80      return 0;
81    }
82
83  if ((size_t) got < size)
84    {
85      *errmsg = "file too short";
86      *err = 0;
87      return 0;
88    }
89
90  return 1;
91}
92
93/* Write data to a file using the simple_object error reporting
94   conventions.  */
95
96int
97simple_object_internal_write (int descriptor, off_t offset,
98			      const unsigned char *buffer, size_t size,
99			      const char **errmsg, int *err)
100{
101  ssize_t wrote;
102
103  if (lseek (descriptor, offset, SEEK_SET) < 0)
104    {
105      *errmsg = "lseek";
106      *err = errno;
107      return 0;
108    }
109
110  wrote = write (descriptor, buffer, size);
111  if (wrote < 0)
112    {
113      *errmsg = "write";
114      *err = errno;
115      return 0;
116    }
117
118  if ((size_t) wrote < size)
119    {
120      *errmsg = "short write";
121      *err = 0;
122      return 0;
123    }
124
125  return 1;
126}
127
128/* Open for read.  */
129
130simple_object_read *
131simple_object_start_read (int descriptor, off_t offset,
132			  const char *segment_name, const char **errmsg,
133			  int *err)
134{
135  unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
136  size_t len, i;
137
138  if (!simple_object_internal_read (descriptor, offset, header,
139				    SIMPLE_OBJECT_MATCH_HEADER_LEN,
140				    errmsg, err))
141    return NULL;
142
143  len = sizeof (format_functions) / sizeof (format_functions[0]);
144  for (i = 0; i < len; ++i)
145    {
146      void *data;
147
148      data = format_functions[i]->match (header, descriptor, offset,
149					 segment_name, errmsg, err);
150      if (data != NULL)
151	{
152	  simple_object_read *ret;
153
154	  ret = XNEW (simple_object_read);
155	  ret->descriptor = descriptor;
156	  ret->offset = offset;
157	  ret->functions = format_functions[i];
158	  ret->data = data;
159	  return ret;
160	}
161    }
162
163  *errmsg = "file not recognized";
164  *err = 0;
165  return NULL;
166}
167
168/* Find all sections.  */
169
170const char *
171simple_object_find_sections (simple_object_read *sobj,
172			     int (*pfn) (void *, const char *, off_t, off_t),
173			     void *data,
174			     int *err)
175{
176  return sobj->functions->find_sections (sobj, pfn, data, err);
177}
178
179/* Internal data passed to find_one_section.  */
180
181struct find_one_section_data
182{
183  /* The section we are looking for.  */
184  const char *name;
185  /* Where to store the section offset.  */
186  off_t *offset;
187  /* Where to store the section length.  */
188  off_t *length;
189  /* Set if the name is found.  */
190  int found;
191};
192
193/* Internal function passed to find_sections.  */
194
195static int
196find_one_section (void *data, const char *name, off_t offset, off_t length)
197{
198  struct find_one_section_data *fosd = (struct find_one_section_data *) data;
199
200  if (strcmp (name, fosd->name) != 0)
201    return 1;
202
203  *fosd->offset = offset;
204  *fosd->length = length;
205  fosd->found = 1;
206
207  /* Stop iteration.  */
208  return 0;
209}
210
211/* Find a section.  */
212
213int
214simple_object_find_section (simple_object_read *sobj, const char *name,
215			    off_t *offset, off_t *length,
216			    const char **errmsg, int *err)
217{
218  struct find_one_section_data fosd;
219
220  fosd.name = name;
221  fosd.offset = offset;
222  fosd.length = length;
223  fosd.found = 0;
224
225  *errmsg = simple_object_find_sections (sobj, find_one_section,
226					 (void *) &fosd, err);
227  if (*errmsg != NULL)
228    return 0;
229  if (!fosd.found)
230    return 0;
231  return 1;
232}
233
234/* Fetch attributes.  */
235
236simple_object_attributes *
237simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
238				int *err)
239{
240  void *data;
241  simple_object_attributes *ret;
242
243  data = sobj->functions->fetch_attributes (sobj, errmsg, err);
244  if (data == NULL)
245    return NULL;
246  ret = XNEW (simple_object_attributes);
247  ret->functions = sobj->functions;
248  ret->data = data;
249  return ret;
250}
251
252/* Release an simple_object_read.  */
253
254void
255simple_object_release_read (simple_object_read *sobj)
256{
257  sobj->functions->release_read (sobj->data);
258  XDELETE (sobj);
259}
260
261/* Merge attributes.  */
262
263const char *
264simple_object_attributes_merge (simple_object_attributes *to,
265				simple_object_attributes *from,
266				int *err)
267{
268  if (to->functions != from->functions)
269    {
270      *err = 0;
271      return "different object file format";
272    }
273  return to->functions->attributes_merge (to->data, from->data, err);
274}
275
276/* Release an attributes structure.  */
277
278void
279simple_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
287simple_object_write *
288simple_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
309simple_object_write_section *
310simple_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
340const char *
341simple_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
381const char *
382simple_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
390void
391simple_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