Subversion Repositories Kolibri OS

Rev

Rev 5191 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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.   &simple_object_xcoff_functions
  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.  
  73.   do
  74.     {
  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.     }
  89.     }
  90.   while (size > 0);
  91.  
  92.   if (size > 0)
  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.  
  117.   do
  118.     {
  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.     }
  133.     }
  134.   while (size > 0);
  135.  
  136.   if (size > 0)
  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.  
  279. /* Merge attributes.  */
  280.  
  281. const char *
  282. simple_object_attributes_merge (simple_object_attributes *to,
  283.                                 simple_object_attributes *from,
  284.                                 int *err)
  285. {
  286.   if (to->functions != from->functions)
  287.     {
  288.       *err = 0;
  289.       return "different object file format";
  290.     }
  291.   return to->functions->attributes_merge (to->data, from->data, err);
  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. }
  442.