home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / binutils-1.8.x.tar.gz / binutils-1.8.x.tar / binutils / hp-bin / hpxt.c < prev    next >
C/C++ Source or Header  |  1989-03-03  |  29KB  |  1,072 lines

  1. /* Program to translate binary format files from HP-UX to GNU.
  2.    Input formats for HP 9000 series 200/300 only.
  3.    Copyright (C) 1988 Free Software Foundation, Inc.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 1, or (at your option)
  8.    any 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include <stdio.h>
  20. #include <varargs.h>
  21. #include <fcntl.h>
  22. #include <sys/file.h>
  23. #include <string.h>
  24. #define index(s, c) strchr (s, c)
  25. #define bzero(p, n) memset (p, 0, n)
  26. #include "ioutil.h"
  27.  
  28. #define forward extern
  29.  
  30. /* IO primitives */
  31.  
  32. void
  33. xread (input_file, buffer, length)
  34.      int input_file;
  35.      char *buffer;
  36.      int length;
  37. {
  38.   if ((iou_read (input_file, buffer, length)) != length)
  39.     iou_error ("read failed to complete");
  40.   return;
  41. }
  42.  
  43. /* HP-UX data structure descriptions */
  44.  
  45. struct hp_magic
  46.   {
  47.     unsigned short system_id;
  48.     unsigned short file_type;
  49.   };
  50.  
  51. #define HP_SYSID_98x6        0x020A
  52. #define HP_SYSID_9000S200    0x020C
  53.  
  54. #define HP_SYSID_OK(sysid)                        \
  55.   (((sysid) == HP_SYSID_9000S200)                    \
  56.    || ((sysid) == HP_SYSID_98x6))
  57.  
  58. #define HP_FILETYPE_RELOC    0x0106 /* relocatable only */
  59. #define HP_FILETYPE_EXEC    0x0107 /* normal executable */
  60. #define HP_FILETYPE_SHARE    0x0108 /* shared executable */
  61. #define HP_FILETYPE_DEMAND    0x010B /* demand-load executable */
  62.  
  63. #define HP_FILETYPE_OK(filetype)                    \
  64.   (((filetype) == HP_FILETYPE_EXEC)                    \
  65.    || ((filetype) == HP_FILETYPE_SHARE)                    \
  66.    || ((filetype) == HP_FILETYPE_DEMAND)                \
  67.    || ((filetype) == HP_FILETYPE_RELOC))
  68.  
  69. #define HP_MAGIC_OK(magic)                        \
  70.   ((HP_SYSID_OK ((magic) . system_id))                    \
  71.    && (HP_FILETYPE_OK ((magic) . file_type)))
  72.  
  73. struct hp_exec
  74.   {
  75.     struct hp_magic a_magic;
  76.     short a_stamp;        /* version id */
  77.     short a_unused;
  78.     long a_sparehp;
  79.     long a_text;        /* size of text segment */
  80.     long a_data;        /* size of data segment */
  81.     long a_bss;            /* size of bss segment */
  82.     long a_trsize;        /* text relocation size */
  83.     long a_drsize;        /* data relocation size */
  84.     long a_pasint;        /* pascal interface size */
  85.     long a_lesyms;        /* symbol table size */
  86.     long a_dnttsize;        /* debug name table size */
  87.     long a_entry;        /* entry point */
  88.     long a_sltsize;        /* source line table size */
  89.     long a_vtsize;        /* value table size */
  90.     long a_spare3;
  91.     long a_spare4;
  92.   };
  93.  
  94. #define HP_EXEC_MAGIC(header) (((header) . a_magic) . file_type)
  95.  
  96. #define HP_PAGE_SIZE 0x1000
  97.  
  98. #define HP_PAGE_SEEK(descriptor, header, offset)            \
  99. {                                    \
  100.   if ((HP_EXEC_MAGIC (header)) == HP_FILETYPE_DEMAND)            \
  101.     {                                    \
  102.       int HP_PAGE_SEEK_remainder;                    \
  103.                                     \
  104.       HP_PAGE_SEEK_remainder = ((offset) % HP_PAGE_SIZE);        \
  105.       if (HP_PAGE_SEEK_remainder != 0)                    \
  106.     iou_lseek                            \
  107.       ((descriptor), (HP_PAGE_SIZE - HP_PAGE_SEEK_remainder), 1);    \
  108.     }                                    \
  109. }
  110.  
  111. struct hp_nlist
  112.   {
  113.     long n_value;
  114.     unsigned char n_type;
  115.     unsigned char n_length;    /* length of ascii symbol name */
  116.     short n_almod;        /* alignment mod */
  117.     short n_unused;
  118.   };
  119.  
  120. #define HP_SYMTYPE_UNDEFINED    0x00
  121. #define HP_SYMTYPE_ABSOLUTE    0x01
  122. #define HP_SYMTYPE_TEXT        0x02
  123. #define HP_SYMTYPE_DATA        0x03
  124. #define HP_SYMTYPE_BSS        0x04
  125. #define HP_SYMTYPE_COMMON    0x05
  126. #define HP_SYMTYPE_FILENAME    0x1F
  127.  
  128. #define HP_SYMTYPE_ALIGN    0x10
  129. #define HP_SYMTYPE_EXTERNAL    0x20
  130.  
  131. #define HP_SYMTYPE_TYPE        0x0F
  132.  
  133. struct hp_relocation_info
  134.   {
  135.     long r_address;        /* position of relocation in segment */
  136.     short r_symbolnum;        /* id of the symbol of external relocations */
  137.     char r_segment;
  138.     char r_length;
  139.   };
  140.  
  141. #define HP_RSEGMENT_TEXT    0x00
  142. #define HP_RSEGMENT_DATA    0x01
  143. #define HP_RSEGMENT_BSS        0x02
  144. #define HP_RSEGMENT_EXTERNAL    0x03
  145. #define HP_RSEGMENT_NOOP    0x3F
  146.  
  147. #define HP_RLENGTH_BYTE        0x00
  148. #define HP_RLENGTH_WORD        0x01
  149. #define HP_RLENGTH_LONG        0x02
  150. #define HP_RLENGTH_ALIGN    0x03
  151.  
  152. #define HP_ARMAG "!<arch>\n"
  153. #define HP_SARMAG 8
  154. #define HP_ARFMAG "`\n"
  155.  
  156. struct hp_ar_hdr
  157.   {
  158.     char ar_name [16];        /* file member name - `/' terminated */
  159.     char ar_date [12];        /* file member date - decimal */
  160.     char ar_uid [6];        /* file member user id - decimal */
  161.     char ar_gid [6];        /* file member group id - decimal */
  162.     char ar_mode [8];        /* file member mode - octal */
  163.     char ar_size [10];        /* file member size - decimal */
  164.     char ar_fmag [2];        /* ARFMAG - string to end header */
  165.   };
  166.  
  167. struct hp_ar_symtab_hdr
  168.   {
  169.     unsigned short n_entries;
  170.     long string_table_size;
  171.   };
  172.  
  173. struct hp_ar_symtab_entry
  174.   {
  175.     long string_index;
  176.     long file_index;
  177.   };
  178.  
  179. /* GNU data structure descriptions */
  180.  
  181. #ifdef hpux
  182.  
  183. /* The `exec' structure and overall layout must be close to HP's when
  184.    we are running on an HP system, otherwise we will not be able to
  185.    execute the resulting file. */
  186.  
  187. #define GNU_OMAGIC HP_FILETYPE_EXEC
  188. #define GNU_NMAGIC HP_FILETYPE_SHARE
  189. #define GNU_ZMAGIC HP_FILETYPE_SHARE
  190.  
  191. struct gnu_exec
  192.   {
  193.     struct hp_magic a_magic;
  194.     unsigned long a_spare1;
  195.     unsigned long a_spare2;
  196.     unsigned long a_text;    /* size of text segment */
  197.     unsigned long a_data;    /* size of data segment */
  198.     unsigned long a_bss;    /* size of bss segment */
  199.     unsigned long a_trsize;    /* text relocation size */
  200.     unsigned long a_drsize;    /* data relocation size */
  201.     unsigned long a_spare3;    /* HP = pascal interface size */
  202.     unsigned long a_spare4;    /* HP = symbol table size */
  203.     unsigned long a_spare5;    /* HP = debug name table size */
  204.     unsigned long a_entry;    /* entry point */
  205.     unsigned long a_spare6;    /* HP = source line table size */
  206.     unsigned long a_spare7;    /* HP = value table size */
  207.     unsigned long a_syms;    /* symbol table size */
  208.     unsigned long a_spare8;
  209.   };
  210.  
  211. #define GNU_EXEC_MAGIC(header) (((header) . a_magic) . file_type)
  212.  
  213. #define GNU_EXEC_SET_MAGIC(header, magic)                \
  214. {                                    \
  215.   (((header) . a_magic) . system_id) = HP_SYSID_9000S200;        \
  216.   (((header) . a_magic) . file_type) = (magic);                \
  217. }
  218.  
  219. #define GNU_PAGE_SEEK_HEADER HP_PAGE_SEEK
  220. #define GNU_PAGE_SEEK_TEXT HP_PAGE_SEEK
  221.  
  222. #else /* not hpux */
  223.  
  224. #define    GNU_OMAGIC    0407    /* old impure format */
  225. #define    GNU_NMAGIC    0410    /* read-only text */
  226. #define    GNU_ZMAGIC    0413    /* demand load format */
  227.  
  228. struct gnu_exec
  229.   {
  230.     unsigned long a_magic;    /* magic number */
  231.     unsigned long a_text;    /* size of text segment */
  232.     unsigned long a_data;    /* size of initialized data */
  233.     unsigned long a_bss;    /* size of uninitialized data */
  234.     unsigned long a_syms;    /* size of symbol table */
  235.     unsigned long a_entry;    /* entry point */
  236.     unsigned long a_trsize;    /* size of text relocation */
  237.     unsigned long a_drsize;    /* size of data relocation */
  238.   };
  239.  
  240. #define GNU_EXEC_MAGIC(header) ((header) . a_magic)
  241. #define GNU_EXEC_SET_MAGIC(header, magic) ((header) . a_magic) = (magic)
  242.  
  243. #define GNU_PAGE_SIZE 0x400
  244.  
  245. #define GNU_PAGE_SEEK_HEADER(descriptor, header, offset)        \
  246. {                                    \
  247.   if ((GNU_EXEC_MAGIC (header)) == GNU_ZMAGIC)                \
  248.     {                                    \
  249.       int GNU_PAGE_SEEK_remainder;                    \
  250.                                     \
  251.       GNU_PAGE_SEEK_remainder = ((offset) % GNU_PAGE_SIZE);        \
  252.       if (GNU_PAGE_SEEK_remainder != 0)                    \
  253.     iou_lseek                            \
  254.       ((descriptor), (GNU_PAGE_SIZE - GNU_PAGE_SEEK_remainder), 1);    \
  255.     }                                    \
  256. }
  257.  
  258. #define GNU_PAGE_SEEK_TEXT(descriptor, header, offset)
  259.  
  260. #endif /* hpux */
  261.  
  262. struct gnu_nlist
  263.   {
  264.     union
  265.       {
  266.     char *n_name;        /* for use when in-core */
  267.     long n_strx;        /* index into file string table */
  268.       } n_un;
  269.     unsigned char n_type;    /* type flag (N_TEXT,..)  */
  270.     char n_other;        /* unused */
  271.     short n_desc;        /* see <stab.h> */
  272.     unsigned long n_value;    /* value of symbol (or sdb offset) */
  273.   };
  274.  
  275. #define    GNU_SYMTYPE_UNDEFINED    0x0
  276. #define    GNU_SYMTYPE_ABSOLUTE    0x2
  277. #define    GNU_SYMTYPE_TEXT    0x4
  278. #define    GNU_SYMTYPE_DATA    0x6
  279. #define    GNU_SYMTYPE_BSS        0x8
  280. #define    GNU_SYMTYPE_COMMON    0x12
  281. #define    GNU_SYMTYPE_FILENAME    0x1F
  282. #define    GNU_SYMTYPE_EXTERNAL    0x01
  283.  
  284. struct gnu_relocation_info
  285.   {
  286.     long r_address;        /* address which is relocated */
  287.     unsigned int
  288.       r_symbolnum : 24,        /* local symbol ordinal */
  289.       r_pcrel : 1,        /* was relocated pc relative already */
  290.       r_length : 2,        /* BYTE, WORD, or LONG */
  291.       r_extern : 1,        /* does not include value of sym referenced */
  292.       : 4;            /* nothing, yet */
  293.   };
  294.  
  295. #define GNU_RLENGTH_BYTE    0x00
  296. #define GNU_RLENGTH_WORD    0x01
  297. #define GNU_RLENGTH_LONG    0x02
  298.  
  299. #define    GNU_ARMAG "!<arch>\n"
  300. #define    GNU_SARMAG 8
  301. #define    GNU_ARFMAG "`\n"
  302.  
  303. struct gnu_ar_hdr
  304.   {
  305.     char ar_name [16];
  306.     char ar_date [12];
  307.     char ar_uid [6];
  308.     char ar_gid [6];
  309.     char ar_mode [8];
  310.     char ar_size [10];
  311.     char ar_fmag [2];
  312.   };
  313.  
  314. struct gnu_symdef
  315.   {
  316.     int symbol_name_string_index;
  317.     int library_member_offset;
  318.   };
  319.  
  320. /* List abstraction */
  321.  
  322. struct pair
  323.   {
  324.     char *car;
  325.     char *cdr;
  326.   };
  327.  
  328. struct pair *
  329. pair_cons (car, cdr)
  330.      char *car;
  331.      char *cdr;
  332. {
  333.   register struct pair *result;
  334.  
  335.   result = ((struct pair *) (iou_malloc (sizeof (struct pair))));
  336.   (result -> car) = car;
  337.   (result -> cdr) = cdr;
  338.   return (result);
  339. }
  340.  
  341. #define LIST_CDR(list) ((struct pair *) ((list) -> cdr))
  342. #define LIST_SET_CDR(list, newcdr) (list -> cdr) = ((char *) newcdr)
  343.  
  344. struct pair *
  345. list_reverse (list)
  346.      register struct pair *list;
  347. {
  348.   register struct pair *previous;
  349.   register struct pair *next;
  350.  
  351.   previous = NULL;
  352.   while (list != NULL)
  353.     {
  354.       next = (LIST_CDR (list));
  355.       LIST_SET_CDR (list, previous);
  356.       previous = list;
  357.       list = next;
  358.     }
  359.   return (previous);
  360. }
  361.  
  362. struct pair *
  363. read_list (input_file, n_bytes, field_name, read_item, length)
  364.      int input_file;
  365.      int n_bytes;
  366.      char * field_name;
  367.      char * (* read_item) ();
  368.      register int * length;    /* return value */
  369. {
  370.   register struct pair *result;
  371.  
  372.   result = NULL;
  373.   (* length) = 0;
  374.   while (n_bytes > 0)
  375.     {
  376.       result = (pair_cons (((* read_item) (input_file, (& n_bytes))), result));
  377.       (* length) += 1;
  378.     }
  379.   if (n_bytes != 0)
  380.     iou_error ("%s field size incorrect", field_name);
  381.   return (list_reverse (result));
  382. }
  383.  
  384. /* Symbol Table */
  385.  
  386. struct gnu_nlist *
  387. read_symbol (input_file, n_bytes)
  388.      int input_file;
  389.      int *n_bytes;        /* return value */
  390. {
  391.   struct hp_nlist input_nlist;
  392.   register struct gnu_nlist *output_nlist;
  393.   register char *name;
  394.  
  395.   {
  396.     register int name_length;
  397.  
  398.     xread (input_file, (& input_nlist), (sizeof (input_nlist)));
  399.     name_length = (input_nlist . n_length);
  400.     name = (iou_malloc (name_length + 1));
  401.     xread (input_file, name, name_length);
  402.     (name [name_length]) = '\0';
  403.     (* n_bytes) -= ((sizeof (input_nlist)) + name_length);
  404.   }
  405.  
  406.   output_nlist =
  407.     ((struct gnu_nlist *) (iou_malloc (sizeof (struct gnu_nlist))));
  408.   ((output_nlist -> n_un) . n_name) = name;
  409.   (output_nlist -> n_other) = 0;
  410.   (output_nlist -> n_desc) = 0;
  411.   (output_nlist -> n_value) = (input_nlist . n_value);
  412.  
  413.   {
  414.     register int name_type;
  415.  
  416.     name_type = (input_nlist . n_type);
  417.     if ((name_type & HP_SYMTYPE_ALIGN) != 0)
  418.       iou_error ("aligned symbol encountered: %s", name);
  419.     if (name_type == HP_SYMTYPE_FILENAME)
  420.       (output_nlist -> n_type) = GNU_SYMTYPE_FILENAME;
  421.     else
  422.       {
  423.     switch (name_type & HP_SYMTYPE_TYPE)
  424.       {
  425.       case HP_SYMTYPE_UNDEFINED:
  426.         (output_nlist -> n_type) = GNU_SYMTYPE_UNDEFINED;
  427.         break;
  428.  
  429.       case HP_SYMTYPE_ABSOLUTE:
  430.         (output_nlist -> n_type) = GNU_SYMTYPE_ABSOLUTE;
  431.         break;
  432.  
  433.       case HP_SYMTYPE_TEXT:
  434.         (output_nlist -> n_type) = GNU_SYMTYPE_TEXT;
  435.         break;
  436.  
  437.       case HP_SYMTYPE_DATA:
  438.         (output_nlist -> n_type) = GNU_SYMTYPE_DATA;
  439.         break;
  440.  
  441.       case HP_SYMTYPE_BSS:
  442.         (output_nlist -> n_type) = GNU_SYMTYPE_BSS;
  443.         break;
  444.  
  445.       case HP_SYMTYPE_COMMON:
  446.         (output_nlist -> n_type) = GNU_SYMTYPE_COMMON;
  447.         break;
  448.  
  449.       default:
  450.         iou_error ("unknown symbol type encountered: %x", name_type);
  451.       }
  452.     if ((name_type & HP_SYMTYPE_EXTERNAL) != 0)
  453.       (output_nlist -> n_type) |= GNU_SYMTYPE_EXTERNAL;
  454.       }
  455.   }
  456.  
  457.   return (output_nlist);
  458. }
  459.  
  460. struct pair *
  461. read_symbol_table (input_file, n_bytes, length)
  462.      int input_file;
  463.      int n_bytes;
  464.      int * length;        /* return value */
  465. {
  466.   return
  467.     (read_list (input_file, n_bytes, "symbol table", read_symbol, length));
  468. }
  469.  
  470. void
  471. write_symbol_table (output_file, symbol_table, length)
  472.      int output_file;
  473.      struct pair *symbol_table;
  474.      int length;
  475. {
  476.   register struct pair *scan;
  477.   register char *name;
  478.   struct gnu_nlist output_nlist;
  479.   int string_table_index;
  480.  
  481.   (output_nlist . n_other) = 0;
  482.   (output_nlist . n_desc) = 0;
  483.  
  484.   string_table_index = (sizeof (string_table_index));
  485.   for (scan = symbol_table; (scan != NULL); scan = (LIST_CDR (scan)))
  486.     {
  487.       register struct gnu_nlist *symbol;
  488.  
  489.       symbol = ((struct gnu_nlist *) (scan -> car));
  490.       name = ((symbol -> n_un) . n_name);
  491.  
  492.       ((output_nlist . n_un) . n_strx) = string_table_index;
  493.       (output_nlist . n_type) = (symbol -> n_type);
  494.       (output_nlist . n_value) = (symbol -> n_value);
  495.       iou_write (output_file, (& output_nlist), (sizeof (output_nlist)));
  496.  
  497.       string_table_index += ((strlen (name)) + 1);
  498.       (scan -> car) = name;
  499.       iou_free (symbol);
  500.     }
  501.   iou_write
  502.     (output_file, (& string_table_index), (sizeof (string_table_index)));
  503.  
  504.   scan = symbol_table;
  505.   while (scan != NULL)
  506.     {
  507.       register struct pair *cdr;
  508.  
  509.       name = (scan -> car);
  510.       iou_write (output_file, name, ((strlen (name)) + 1));
  511.       iou_free (name);
  512.       cdr = (LIST_CDR (scan));
  513.       iou_free (scan);
  514.       scan = cdr;
  515.     }
  516.   return;
  517. }
  518.  
  519. /* Relocation Info */
  520.  
  521. struct gnu_relocation_info *
  522. read_relocation_info_1 (input_file, n_bytes)
  523.      int input_file;
  524.      register int * n_bytes;    /* return value */
  525. {
  526.   struct hp_relocation_info input_info;
  527.   register struct gnu_relocation_info *output_info;
  528.  
  529.   xread (input_file, (& input_info), (sizeof (input_info)));
  530.   (* n_bytes) -= (sizeof (input_info));
  531.  
  532.   output_info =
  533.     ((struct gnu_relocation_info *)
  534.      (iou_malloc (sizeof (struct gnu_relocation_info))));
  535.   (output_info -> r_pcrel) = 0;
  536.   (output_info -> r_address) = (input_info . r_address);
  537.  
  538.   switch (input_info . r_segment)
  539.     {
  540.     case HP_RSEGMENT_TEXT:
  541.       (output_info -> r_symbolnum) = GNU_SYMTYPE_TEXT;
  542.       (output_info -> r_extern) = 0;
  543.       break;
  544.  
  545.     case HP_RSEGMENT_DATA:
  546.       (output_info -> r_symbolnum) = GNU_SYMTYPE_DATA;
  547.       (output_info -> r_extern) = 0;
  548.       break;
  549.  
  550.     case HP_RSEGMENT_BSS:
  551.       (output_info -> r_symbolnum) = GNU_SYMTYPE_BSS;
  552.       (output_info -> r_extern) = 0;
  553.       break;
  554.  
  555.     case HP_RSEGMENT_EXTERNAL:
  556.       (output_info -> r_symbolnum) = (input_info . r_symbolnum);
  557.       (output_info -> r_extern) = 1;
  558.       break;
  559.  
  560.     default:
  561.       iou_error
  562.     ("illegal relocation segment type: %x", (input_info . r_segment));
  563.     }
  564.  
  565.   switch (input_info . r_length)
  566.     {
  567.     case HP_RLENGTH_BYTE:
  568.       (output_info -> r_length) = GNU_RLENGTH_BYTE;
  569.       break;
  570.  
  571.     case HP_RLENGTH_WORD:
  572.       (output_info -> r_length) = GNU_RLENGTH_WORD;
  573.       break;
  574.  
  575.     case HP_RLENGTH_LONG:
  576.       (output_info -> r_length) = GNU_RLENGTH_LONG;
  577.       break;
  578.  
  579.     default:
  580.       iou_error ("illegal relocation length: %x", (input_info . r_length));
  581.     }
  582.  
  583.   return (output_info);
  584. }
  585.  
  586. struct pair *
  587. read_relocation_info (input_file, n_bytes, length)
  588.      int input_file;
  589.      int n_bytes;
  590.      int * length;
  591. {
  592.   return
  593.     (read_list
  594.      (input_file, n_bytes, "relocation info", read_relocation_info_1, length));
  595. }
  596.  
  597. void
  598. write_relocation_info (output_file, relocation_info, length)
  599.      int output_file;
  600.      struct pair *relocation_info;
  601.      int length;
  602. {
  603.   register struct pair *this;
  604.   register struct gnu_relocation_info *car;
  605.   register struct pair *cdr;
  606.  
  607.   this = relocation_info;
  608.   while (this != NULL)
  609.     {
  610.       car = ((struct gnu_relocation_info *) (this -> car));
  611.       iou_write (output_file, car, (sizeof (struct gnu_relocation_info)));
  612.       iou_free (car);
  613.       cdr = (LIST_CDR (this));
  614.       iou_free (this);
  615.       this = cdr;
  616.     }
  617.   return;
  618. }
  619.  
  620. /* Convert an executable (or relocatable) file. */
  621.  
  622. void
  623. process_executable_file (input_file, output_file)
  624.      int input_file;
  625.      int output_file;
  626. {
  627.   struct hp_exec input_exec;
  628.   struct gnu_exec output_exec;
  629.   char *text_segment;
  630.   char *data_segment;
  631.   struct pair *symbol_table;
  632.   int symbol_table_length;
  633.   struct pair *text_relocation_info;
  634.   int text_relocation_info_length;
  635.   struct pair *data_relocation_info;
  636.   int data_relocation_info_length;
  637.  
  638.   xread (input_file, (& input_exec), (sizeof (input_exec)));
  639.   HP_PAGE_SEEK (input_file, input_exec, (sizeof (input_exec)));
  640.  
  641.   if ((input_exec . a_text) != 0)
  642.     {
  643.       text_segment = (iou_malloc (input_exec . a_text));
  644.       xread (input_file, text_segment, (input_exec . a_text));
  645.       HP_PAGE_SEEK (input_file, input_exec, (input_exec . a_text));
  646.     }
  647.   else
  648.     text_segment = NULL;
  649.  
  650.   if ((input_exec . a_data) != 0)
  651.     {
  652.       data_segment = (iou_malloc (input_exec . a_data));
  653.       xread (input_file, data_segment, (input_exec . a_data));
  654.       HP_PAGE_SEEK (input_file, input_exec, (input_exec . a_data));
  655.     }
  656.   else
  657.     data_segment = NULL;
  658.  
  659.   /* Skip the pascal interface text */
  660.   iou_lseek (input_file, (input_exec . a_pasint), 1);
  661.  
  662.   symbol_table =
  663.     (read_symbol_table
  664.      (input_file, (input_exec . a_lesyms), (& symbol_table_length)));
  665.  
  666.   /* Skip the debugging tables */
  667.   iou_lseek
  668.     (input_file,
  669.      ((input_exec . a_dnttsize)
  670.       + (input_exec . a_sltsize)
  671.       + (input_exec . a_vtsize)),
  672.      1);
  673.  
  674.   text_relocation_info =
  675.     (read_relocation_info
  676.      (input_file, (input_exec . a_trsize), (& text_relocation_info_length)));
  677.   data_relocation_info =
  678.     (read_relocation_info
  679.      (input_file, (input_exec . a_drsize), (& data_relocation_info_length)));
  680.  
  681.   bzero ((& output_exec), (sizeof (output_exec)));
  682.   switch (HP_EXEC_MAGIC (input_exec))
  683.     {
  684.     case HP_FILETYPE_RELOC:
  685.     case HP_FILETYPE_EXEC:
  686.       GNU_EXEC_SET_MAGIC (output_exec, GNU_OMAGIC);
  687.       break;
  688.  
  689.     case HP_FILETYPE_SHARE:
  690.       GNU_EXEC_SET_MAGIC (output_exec, GNU_NMAGIC);
  691.       break;
  692.  
  693.     case HP_FILETYPE_DEMAND:
  694.       GNU_EXEC_SET_MAGIC (output_exec, GNU_ZMAGIC);
  695.       break;
  696.  
  697.     default:
  698.       iou_error ("unknown magic type: %x", (HP_EXEC_MAGIC (input_exec)));
  699.     }
  700.   (output_exec . a_text) = (input_exec . a_text);
  701.   (output_exec . a_data) = (input_exec . a_data);
  702.   (output_exec . a_bss) = (input_exec . a_bss);
  703.   (output_exec . a_syms) = (symbol_table_length * (sizeof (struct gnu_nlist)));
  704.   (output_exec . a_entry) = (input_exec . a_entry);
  705.   (output_exec . a_trsize) = (input_exec . a_trsize);
  706.   (output_exec . a_drsize) = (input_exec . a_drsize);
  707.  
  708.   iou_write (output_file, (& output_exec), (sizeof (output_exec)));
  709.   GNU_PAGE_SEEK_HEADER (output_file, output_exec, (sizeof (output_exec)));
  710.   if (text_segment != NULL)
  711.     {
  712.       iou_write (output_file, text_segment, (output_exec . a_text));
  713.       iou_free (text_segment);
  714.       GNU_PAGE_SEEK_TEXT (output_file, output_exec, (output_exec . a_text));
  715.     }
  716.   if (data_segment != NULL)
  717.     {
  718.       iou_write (output_file, data_segment, (output_exec . a_data));
  719.       iou_free (data_segment);
  720.       GNU_PAGE_SEEK_TEXT (output_file, output_exec, (output_exec . a_data));
  721.     }
  722.   write_relocation_info
  723.     (output_file, text_relocation_info, text_relocation_info_length);
  724.   write_relocation_info
  725.     (output_file, data_relocation_info, data_relocation_info_length);
  726.   write_symbol_table (output_file, symbol_table, symbol_table_length);
  727.  
  728.   return;
  729. }
  730.  
  731. /* Convert an archive file. */
  732.  
  733. /* These procedures take advantage of the fact that the HP and GNU
  734.    formats for struct ar_hdr are virtually identical. */
  735.  
  736. long symtab_start_position;
  737. char *symtab_member_data;
  738. struct hp_ar_symtab_entry *hp_symtab_entries;
  739. struct gnu_symdef *gnu_symtab_entries;
  740. long symtab_entries_length;
  741. long symtab_names_length;
  742.  
  743. void
  744. process_archive_file (input_file, output_file)
  745.      int input_file;
  746.      int output_file;
  747. {
  748.   int start_position;
  749.   int length;
  750.   struct hp_ar_hdr input_header;
  751.   int member_length;
  752.   forward void process_archive_symtab ();
  753.   forward void update_symtab_entries ();
  754.   forward void output_symtab_entries ();
  755.   forward void process_archive_entry ();
  756.  
  757.   gnu_symtab_entries = NULL;
  758.   while (1)
  759.     {
  760.       start_position = (iou_lseek (input_file, 0, 1));
  761.       length = (read (input_file, (& input_header), (sizeof (input_header))));
  762.       if (length == 0)
  763.     break;
  764.       if (length != (sizeof (input_header)))
  765.     iou_error ("input archive ends prematurely");
  766.       if (((strncmp
  767.         ((input_header . ar_fmag),
  768.          HP_ARFMAG,
  769.          (sizeof (input_header . ar_fmag))))
  770.        != 0)
  771.       ||
  772.       ((sscanf ((input_header . ar_size), "%d", (& member_length)))
  773.        != 1))
  774.     iou_error ("malformatted header of archive member");
  775.  
  776.       if (((input_header . ar_name) [0]) == '/')
  777.     process_archive_symtab
  778.       (input_file, output_file, (& input_header), member_length);
  779.       else
  780.     {
  781.       if (gnu_symtab_entries != NULL)
  782.         update_symtab_entries
  783.           (start_position, (iou_lseek (output_file, 0, 1)));
  784.       process_archive_entry (input_file, output_file, (& input_header),
  785.                  member_length);
  786.     }
  787.     }
  788.   if (gnu_symtab_entries != NULL)
  789.     output_symtab_entries (output_file, (& input_header));
  790.   return;
  791. }
  792.  
  793. #ifdef DEBUG_SYMTAB
  794.  
  795. void
  796. dump_symtab_data ()
  797. {
  798.   register struct hp_ar_symtab_entry *symtab_entries;
  799.   register char *symtab_names;
  800.   register int i;
  801.  
  802.   symtab_names = (symtab_member_data + (sizeof (struct hp_ar_symtab_hdr)));
  803.   symtab_entries =
  804.     ((struct hp_ar_symtab_entry *) (symtab_names + symtab_names_length));
  805.   for (i = 0; (i < symtab_entries_length); i += 1)
  806.     {
  807.       fprintf
  808.     (stdout,
  809.      "Entry %d: string_index = %d; file_index = %d; name = %s\n",
  810.      i,
  811.      ((symtab_entries [i]) . string_index),
  812.      ((symtab_entries [i]) . file_index),
  813.      (symtab_names + ((symtab_entries [i]) . string_index)));
  814.     }
  815.   fflush (stdout);
  816.   return;
  817. }
  818.  
  819. #endif /* DEBUG_SYMTAB */
  820.  
  821. void
  822. process_archive_symtab (input_file, output_file, input_header, member_length)
  823.      int input_file;
  824.      int output_file;
  825.      struct hp_ar_hdr *input_header;
  826.      int member_length;
  827. {
  828.   long symtab_entries_bytes;
  829.   void initialize_symtab_entries ();
  830.  
  831.   symtab_member_data = (iou_malloc (member_length));
  832.   xread (input_file, symtab_member_data, member_length);
  833.  
  834.   symtab_entries_length =
  835.     (((struct hp_ar_symtab_hdr *) symtab_member_data) -> n_entries);
  836.   symtab_entries_bytes =
  837.     (symtab_entries_length * (sizeof (struct hp_ar_symtab_entry)));
  838.   symtab_names_length =
  839.     (((struct hp_ar_symtab_hdr *) symtab_member_data) -> string_table_size);
  840.  
  841. #ifdef DEBUG_SYMTAB
  842.   dump_symtab_data ();
  843. #endif
  844.  
  845.   {
  846.     char string_buffer [((sizeof (input_header -> ar_name)) + 1)];
  847.  
  848.     sprintf
  849.       (string_buffer, "%-*s", (sizeof (input_header -> ar_name)), "__.SYMDEF");
  850.     strncpy
  851.       ((input_header -> ar_name),
  852.        string_buffer,
  853.        (sizeof (input_header -> ar_name)));
  854.   }
  855.   {
  856.     char string_buffer [((sizeof (input_header -> ar_size)) + 1)];
  857.  
  858.     sprintf
  859.       (string_buffer,
  860.        "%-*d",
  861.        (sizeof (input_header -> ar_size)),
  862.        (symtab_entries_bytes + symtab_names_length + (2 * (sizeof (long)))));
  863.     strncpy
  864.       ((input_header -> ar_size),
  865.        string_buffer,
  866.        (sizeof (input_header -> ar_size)));
  867.   }
  868.   iou_write (output_file, input_header, (sizeof (* input_header)));
  869.   iou_write (output_file, (& symtab_entries_bytes), (sizeof (long)));
  870.  
  871.   /* Leave slot for entries, which we fill in later. */
  872.   symtab_start_position = (iou_lseek (output_file, 0, 1));
  873.   initialize_symtab_entries ();
  874.   iou_lseek (output_file, symtab_entries_bytes, 1);
  875.  
  876.   iou_write (output_file, (& symtab_names_length), (sizeof (long)));
  877.   iou_write
  878.     (output_file,
  879.      (symtab_member_data + (sizeof (struct hp_ar_symtab_hdr))),
  880.      symtab_names_length);
  881.  
  882.   return;
  883. }
  884.  
  885. void
  886. initialize_symtab_entries ()
  887. {
  888.   register struct hp_ar_symtab_entry *scan_hp;
  889.   register struct hp_ar_symtab_entry *end;
  890.   register struct gnu_symdef *scan_gnu;
  891.  
  892.   hp_symtab_entries =
  893.     ((struct hp_ar_symtab_entry *)
  894.      (symtab_member_data
  895.       + (sizeof (struct hp_ar_symtab_hdr))
  896.       + symtab_names_length));
  897.   gnu_symtab_entries =
  898.     ((struct gnu_symdef *)
  899.      (iou_malloc (symtab_entries_length * (sizeof (struct gnu_symdef)))));
  900.  
  901.   scan_hp = hp_symtab_entries;
  902.   end = (scan_hp + symtab_entries_length);
  903.   scan_gnu = gnu_symtab_entries;
  904.   while (scan_hp < end)
  905.     {
  906.       (scan_gnu -> symbol_name_string_index) = (scan_hp -> string_index);
  907.       (scan_gnu -> library_member_offset) = (-1);
  908.       scan_hp += 1;
  909.       scan_gnu += 1;
  910.     }
  911.  
  912.   return;
  913. }
  914.  
  915. void
  916. update_symtab_entries (old_offset, new_offset)
  917.      register long old_offset;
  918.      long new_offset;
  919. {
  920.   register struct hp_ar_symtab_entry *scan_hp;
  921.   register struct hp_ar_symtab_entry *end;
  922.   register struct gnu_symdef *scan_gnu;
  923.  
  924. #ifdef DEBUG_SYMTAB
  925.   fprintf (stdout, "Update: old = %d, new = %d\n", old_offset, new_offset);
  926. #endif
  927.  
  928.   scan_hp = hp_symtab_entries;
  929.   end = (scan_hp + symtab_entries_length);
  930.   scan_gnu = gnu_symtab_entries;
  931.   while (scan_hp < end)
  932.     {
  933.       if ((scan_hp -> file_index) == old_offset)
  934.     {
  935. #ifdef DEBUG_SYMTAB
  936.       fprintf
  937.         (stdout,
  938.          "\t%s\n",
  939.          (symtab_member_data
  940.           + (sizeof (struct hp_ar_symtab_hdr))
  941.           + (scan -> string_index)));
  942. #endif
  943.       (scan_gnu -> library_member_offset) = new_offset;
  944.     }
  945.       scan_hp += 1;
  946.       scan_gnu += 1;
  947.     }
  948.   return;
  949. }
  950.  
  951. void
  952. check_symtab_entries ()
  953. {
  954.   register struct gnu_symdef *scan;
  955.   register struct gnu_symdef *end;
  956.  
  957.   scan = gnu_symtab_entries;
  958.   end = (scan + symtab_entries_length);
  959.   while (scan < end)
  960.     if (((scan++) -> library_member_offset) == (-1))
  961.       iou_error ("Uninitialized __.SYMTAB entry");
  962.  
  963.   return;
  964. }
  965.  
  966. void
  967. output_symtab_entries (output_file, input_header)
  968.      int output_file;
  969.      struct hp_ar_hdr *input_header;
  970. {
  971.   check_symtab_entries ();
  972.   iou_lseek (output_file, symtab_start_position, 0);
  973.   iou_write
  974.     (output_file,
  975.      gnu_symtab_entries,
  976.      (symtab_entries_length * (sizeof (struct gnu_symdef))));
  977.   iou_free (symtab_member_data);
  978.   iou_free (gnu_symtab_entries);
  979.   return;
  980. }
  981.  
  982. void
  983. process_archive_entry (input_file, output_file, input_header, member_length)
  984.      int input_file;
  985.      int output_file;
  986.      struct hp_ar_hdr *input_header;
  987.      int member_length;
  988. {
  989.   long header_position;
  990.   long output_start;
  991.   long output_end;
  992.   long input_end;
  993.  
  994.   /* Strategy: leave a hole for the header, then process the file.
  995.      Afterwards, back up and write the header in place. */
  996.   header_position = (iou_lseek (output_file, 0, 1));
  997.   output_start = (iou_lseek (output_file, (sizeof (* input_header)), 1));
  998.   input_end = ((iou_lseek (input_file, 0, 1)) + member_length);
  999.  
  1000.   process_executable_file (input_file, output_file);
  1001.   if ((iou_lseek (input_file, 0, 1)) != input_end)
  1002.     iou_error ("process_executable_file used wrong amount of input");
  1003.  
  1004.   output_end = (iou_lseek (output_file, 0, 1));
  1005.   iou_lseek (output_file, header_position, 0);
  1006.   (* (index ((input_header -> ar_name), '/'))) = ' ';
  1007.   {
  1008.     char string_buffer [((sizeof (input_header -> ar_size)) + 1)];
  1009.  
  1010.     sprintf
  1011.       (string_buffer,
  1012.        "%-*d",
  1013.        (sizeof (input_header -> ar_size)),
  1014.        (output_end - output_start));
  1015.     strncpy
  1016.       ((input_header -> ar_size),
  1017.        string_buffer,
  1018.        (sizeof (input_header -> ar_size)));
  1019.   }
  1020.   iou_write (output_file, input_header, (sizeof (* input_header)));
  1021.   iou_lseek (output_file, output_end, 0);
  1022.  
  1023.   /* Pad to even byte boundary if needed */
  1024.   if ((input_end & 1) != 0)
  1025.     iou_lseek (input_file, 1, 1);
  1026.   if ((output_end & 1) != 0)
  1027.     iou_write (output_file, "\0", 1);
  1028.  
  1029.   return;
  1030. }
  1031.  
  1032. void
  1033. main (argc, argv)
  1034.      int argc;
  1035.      char *argv[];
  1036. {
  1037.   int input_file;
  1038.   int output_file;
  1039.   register int length;
  1040.   struct hp_magic input_magic;
  1041.  
  1042.   iou_set_program_name (argv);
  1043.   if (argc != 3)
  1044.     {
  1045.       fprintf (stderr, "usage: %s input-file output-file\n", iou_program_name);
  1046.       iou_error ();
  1047.     }
  1048.  
  1049.   input_file = (iou_open ((argv [1]), O_RDONLY));
  1050.   output_file = (iou_open ((argv [2]), (O_WRONLY | O_CREAT | O_TRUNC), 0666));
  1051.  
  1052.   xread (input_file, (& input_magic), (sizeof (input_magic)));
  1053.   if (HP_MAGIC_OK (input_magic))
  1054.     {
  1055.       iou_lseek (input_file, 0, 0);
  1056.       process_executable_file (input_file, output_file);
  1057.     }
  1058.   else
  1059.     {
  1060.       char armag [HP_SARMAG];
  1061.  
  1062.       iou_lseek (input_file, 0, 0);
  1063.       xread (input_file, armag, HP_SARMAG);
  1064.       if ((strncmp (armag, HP_ARMAG, HP_SARMAG)) != 0)
  1065.     iou_error ("input file not executable or archive");
  1066.       iou_write (output_file, GNU_ARMAG, GNU_SARMAG);
  1067.       process_archive_file (input_file, output_file);
  1068.     }
  1069.   exit (0);
  1070.   /*NOTREACHED*/
  1071. }
  1072.