home *** CD-ROM | disk | FTP | other *** search
- ;/* how to compile this thingy:
- gcc2 -O2 -msmall-code -resident hunk2gcc.c -o hunk2gcc -DNDEBUG
- quit
- */
-
- /*
- * Convert amiga object files in the hunk format into a.out-object files.
- * ALINK style (ie. concatenated) libraries are supported as well, in that
- * case a collection of object files is generated, you'll have to run
- * `ar rs libfoo.a obj.*' on them to make an a.out-style library out of
- * them.
- *
- * Currently untested are:
- * o base-relative relocs and references
- * I'll first have to teach gnu-ld how to deal with them ;-)
- * o conversion of load files...
- * o common symbols, amiga objects normally don't use them, sigh
- *
- * Currently not implemented are:
- * o BLINK style indexed libraries (HUNK_LIB and HUNK_INDEX). If you're
- * generating such libraries yourself, you can as well generate oldstyle
- * libraries, and the libraries from Commodore-Amiga are in ALINK format
- * (amiga.lib and friends).
- * This index-format is so weird and complicated that I didn't bother
- * long to decide not to support it. If someone volunteers (you got
- * the source;-)) please send me enhancements!
- *
- * V1.0 91-10-08 M.Wild first hack
- * V1.1 91-10-19 M.Wild add support for CHIP hunk attribute in
- * DATA/BSS hunks (not CODE, ever used??)
- * Now, when are multiple hunks supported ? ;-)
- *
- * This is free software. This means that I don't care what you do with it
- * as long as you don't claim you wrote it. If you enhance it, please
- * send me your diffs!
- * Oh, of course, you use this stuff entirely at your own risk, I'm not
- * responsible for any damage this program might cause to you, your computer,
- * your data, your cat, your whateveryoucanthinkof, no warranty whatsoever is
- * granted.
- *
- * I can be reached on internet as: wild@nessie.cs.id.ethz.ch (Markus Wild)
- *
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/file.h>
- #include <a.out.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
-
- /* This is really <dos/doshunks.h>, which is a 2.0 header file.
- * You can get those 2.0 headers from CATS.
- * Sorry, I'm not allowed to include them here. You may as well take the
- * AmigaDOS Manual 2nd ed. (you'll miss the a4-rel hunks) or 3rd ed. and write
- * the header yourself, it's not that long and difficult
- */
- #include "doshunks.h"
-
- /* strangely enough, this is missing from the doshunks.h file */
- #define HUNK_ATTRIBUTE(h) ((h) >> 30)
- #define HUNK_VALUE(h) ((h) & 0x3fffffff)
- #define HUNK_ATTR_CHIP 0x01
-
- /* These are the symbol names we are generating to denote the limit between
- * the `normal' and `chip' data/bss.
- */
- #define CHIP_DATA_START "__chip_data"
- #define CHIP_BSS_START "__chip_bss"
-
- #ifndef NDEBUG
- #define DP(a) printf a
- #else
- #define DP(a)
- #endif
-
- /* don't introduce the same chaos as with gcc versions... this doesn't
- * include the `real' version, but the compilation date seems to be an
- * even better way to distinguish versions.. */
- static char *version_tag = "\0$VER: hunk2gcc " __DATE__ "\r\n";
-
- extern int errno;
-
- /* my favorite typedefs ;-)) */
- typedef unsigned char uchar;
- typedef unsigned long ulong;
-
- ulong *file_buf = 0;
-
- /* if set no progress reports are output */
- int silent_mode = 0;
-
- struct reloc {
- /* at which offset to relocate */
- int offset;
- /* based on which hunk base */
- int from_hunk, to_hunk;
- int size;
- int pcrel;
- int baserel;
- /* if != -1, the "to_hunk" field is not used */
- int sym_num;
- };
-
- /* NOTE: this symbol definition is compatible with struct nlist, and it will
- * be converted into a struct nlist in 'emit_aout_obj' */
- struct symbol {
- int name; /* string as offset into string table */
- uchar type;
- uchar pad1; /* really n_other */
- short hunk_num; /* really n_desc */
- ulong value;
- };
-
- struct table {
- void *base;
- int el_size;
- int i;
- int max_el;
- };
-
- void
- emit_aout_file (int fd, void *text, void *data, void *chip_data,
- struct exec *hdr, int chip_data_size, int chip_bss_size,
- struct table *ch_tab, struct table *dh_tab, struct table *bh_tab,
- struct table *cdh_tab, struct table *cbh_tab,
- struct table *reloc_tab, struct table *symbol_tab, int max_hunk);
-
- #define TAB_START_SIZE 1024
-
- /* advance the hunk-pointer to the next hunk. Assumes the hunk-pointer is
- * pointing at the length-field currently
- */
- static void inline
- next_hunk(ulong **hp)
- {
- /* skip over the length field and the there given length */
- *hp += 1 + **hp;
- }
-
-
- /* save a lot of space for duplicate string, that all say "only.. with size.. */
- static void inline
- limit_hunk (char *hunk_name)
- {
- fprintf (stderr, "only one %s hunk with size!=0 supported.\n", hunk_name);
- }
-
- /****************************************************************************/
-
- /* these two function maintain the string table. You may only free the last
- * string allocated. (This could be done with an obstack as well, but I really
- * don't need the whole functionality of an obstack, so I kept it simple ;-))
- * Only use the offset, since the table itself may be reallocated.
- */
- char *str_table = 0;
- int strtab_size, strtab_index;
-
- static int inline
- stralloc (int len)
- {
- int res;
-
- /* always include the zero terminator */
- len++;
-
- if (! str_table)
- {
- strtab_size = TAB_START_SIZE;
- /* start the table at index 4, leaving space to later fill in the
- * size of the table */
- strtab_index = 4;
- str_table = malloc (strtab_size);
- }
-
- while (strtab_index + len > strtab_size)
- {
- strtab_size <<= 1;
- str_table = realloc (str_table, strtab_size);
- }
-
- res = strtab_index;
- strtab_index += len;
- return res;
- }
-
- static void inline
- strfree (int str)
- {
- strtab_index = str;
- }
-
- /****************************************************************************/
-
- static void inline
- add_table (struct table *tab, void *el)
- {
- if (tab->i == tab->max_el)
- {
- if (! tab->base)
- {
- tab->max_el = TAB_START_SIZE;
- tab->base = malloc (tab->max_el * tab->el_size);
- }
- else
- {
- tab->max_el <<= 1;
- tab->base = realloc (tab->base, tab->max_el * tab->el_size);
- }
- if (! tab->base)
- {
- fprintf (stderr, "Out of memory adding to table.\n");
- /* exit does close all outstanding files ;-) */
- exit (20);
- }
- }
- bcopy (el, (uchar *)tab->base + (tab->i++ * tab->el_size), tab->el_size);
- }
-
- static void inline
- add_reloc (struct table *tab, int from, int to, int offset,
- int size, int pcrel, int baserel, int sym_num)
- {
- struct reloc r;
-
- DP(("reloc: from=%d, to=%d, off=%d, size=%d, pc=%d, ba=%d, syn=%d\n",
- from, to, offset, size, pcrel, baserel, sym_num));
-
- r.from_hunk = from;
- r.to_hunk = to;
- r.offset = offset;
- r.size = size;
- r.pcrel = pcrel;
- r.baserel = baserel;
- r.sym_num = sym_num;
- add_table (tab, &r);
- }
-
- static void inline
- add_symbol (struct table *tab, int num, ulong type, int value, char *name)
- {
- struct symbol s;
-
- s.hunk_num = num;
- s.type = type >> 24;
- s.value = value;
- s.name = stralloc ((type & 0xffffff)<<2);
- bcopy (name, str_table+s.name, (type & 0xffffff)<<2);
- (str_table+s.name)[(type & 0xffffff)<<2] = 0;
-
- /* some (really stupid..) compilers mention symbols twice, once as
- * a definition, and once as an EXT_SYMB. So we really have to search
- * the symbol_table before adding an EXT_SYMB and check if a symbol of this name
- * isn't already defined for this value. If this hack should slow down
- * the conversion dramatically, I'll have to resort to hashing, I don't
- * like that idea... */
- if (s.type == EXT_SYMB)
- {
- int i;
-
- for (i = 0; i < tab->i; i++)
- /* we have CSE in the compiler, right? ;-)) */
- if (((struct symbol *)tab->base)[i].value == s.value &&
- ((struct symbol *)tab->base)[i].hunk_num == s.hunk_num &&
- ! strcmp (str_table+((struct symbol *)tab->base)[i].name,
- str_table+s.name))
- {
- strfree (s.name);
- return;
- }
- }
-
- add_table (tab, &s);
- }
-
- /****************************************************************************/
-
- void
- digest_objfile (ulong **file_pptr, ulong *max_fp)
- {
- /* this makes it less clumsy.. */
- ulong *file_ptr = *file_pptr;
- static int obj_file_num = 0;
- int units = 0;
- int fd = -1;
- /* if processed hunk has a CHIP attribute */
- int is_chip;
-
- /* buffer-pointers, where text & data sections are stored.
- * Currently only one hunk with size!=0 of type text/data/bss each is
- * supported.
- * There is now an additional buffer to support one chip hunk as well.
- * (chip-bss is supported too, but doesn't need a buffer ;-))
- */
- uchar *text, *data, *chip_data;
- ulong chip_data_size, chip_bss_size;
- struct exec hdr;
-
- /* hunk numbers, needed to associate reloc blocks with segments */
- int hunk_num;
- static struct table code_hunks = { 0, 4, 0, 0 };
- static struct table data_hunks = { 0, 4, 0, 0 };
- static struct table bss_hunks = { 0, 4, 0, 0 };
- static struct table chip_data_hunks = { 0, 4, 0, 0 };
- static struct table chip_bss_hunks = { 0, 4, 0, 0 };
-
- /* static so that no initialization code is required */
- static struct table reloc_tab = { 0, sizeof (struct reloc), 0, 0 };
- static struct table symbol_tab = { 0, sizeof (struct symbol), 0, 0 };
-
- /* (re) init tables */
- strtab_index = 4;
- code_hunks.i =
- data_hunks.i =
- bss_hunks.i =
- chip_data_hunks.i =
- reloc_tab.i =
- symbol_tab.i = 0;
-
-
- while (units < 2)
- {
- switch (HUNK_VALUE(*file_ptr++))
- {
- case HUNK_UNIT:
- DP(("HUNK_UNIT: units = %d\n", units));
- if (units++) break;
- #if 0
- if (! file_ptr[0])
- #endif
- {
- /* need [], not *, so that gcc allocates a fresh copy for
- * mkstemp() to modify! */
- char tmp_nam[] = "obj.YYYY.XXXXXX";
- /* this trick makes mkstemp() lots faster ;-) */
- sprintf (tmp_nam, "obj.%04d.XXXXXX", obj_file_num++);
- if ((fd = mkstemp (tmp_nam)) < 0)
- fprintf (stderr, "Can't create %s (%s). Ignoring it.\n",
- tmp_nam, strerror (errno));
- }
- #if 0
- /* this idea was too good.. there are so many stupid (and duplicate!) names
- * of program units, that this generated ridiculous results... */
-
- else
- {
- char *file_name;
- file_name = alloca (file_ptr[0] + 1);
- strncpy (file_name, (char *)&file_ptr[1], file_ptr[0]);
- if ((fd = open (file_name, O_RDWR|O_CREAT|O_EXCL, 0666)) < 0)
- fprintf (stderr, "Can't create %s: %s. Ignoring it.\n",
- file_name, strerror (errno));
- }
- #endif
-
- /* init data for new object file */
- text = data = chip_data = 0;
- bzero (&hdr, sizeof (hdr));
- chip_data_size = chip_bss_size = 0;
- /* if someone want's to use'em on a sun, why shouldn't we make
- * the files sun-conformant? */
- hdr.a_mid = MID_SUN010;
- hdr.a_magic = OMAGIC;
- hunk_num = 0;
- next_hunk (& file_ptr);
- if (! silent_mode)
- {
- putchar ('.');
- fflush (stdout);
- }
- break;
-
- case HUNK_NAME:
- case HUNK_DEBUG:
- DP(("HUNK_NAME/DEBUG\n"));
- /* this hunk is silently ignored ;-) */
- next_hunk (& file_ptr);
- break;
-
- case HUNK_OVERLAY:
- fprintf (stderr, "warning: overlay hunk ignored!\n");
- next_hunk (& file_ptr);
- break;
-
- case HUNK_BREAK:
- fprintf (stderr, "warning: break hunk ignored!\n");
- break;
-
- case HUNK_HEADER:
- fprintf (stderr, "warning: load file header encountered.\n");
- fprintf (stderr, " are you sure this is an object file?\n");
- /* nevertheless, we go on. perhaps some day I need this feature to
- * be able to convert a loadfile into an object file?! */
-
- /* skip (never used) resident library names */
- while (file_ptr[0]) next_hunk (& file_ptr);
- /* skip null-word, table_size, F & L, and size-table */
- file_ptr += 4 + (file_ptr[1] - file_ptr[2] + 1);
- break;
-
- case HUNK_CODE:
- DP(("HUNK_CODE, size = $%x\n", file_ptr[0] << 2));
- is_chip = HUNK_ATTRIBUTE(file_ptr[-1]) == HUNK_ATTR_CHIP;
- if (is_chip)
- fprintf (stderr, "CHIP code hunks are not supported, "
- "ignoring CHIP attribute\n");
- if (file_ptr[0])
- {
- /* only accept one code hunk with size != 0 */
- if (hdr.a_text)
- limit_hunk ("code");
- else
- {
- text = (uchar *)&file_ptr[1];
- hdr.a_text = file_ptr[0] << 2;
- }
- }
- next_hunk (& file_ptr);
- add_table (& code_hunks, &hunk_num);
- hunk_num++;
- break;
-
- case HUNK_DATA:
- DP(("HUNK_DATA, size = $%x\n", file_ptr[0] << 2));
- is_chip = HUNK_ATTRIBUTE(file_ptr[-1]) == HUNK_ATTR_CHIP;
- if (file_ptr[0])
- {
- /* only accept one data hunk with size != 0 */
- if (is_chip)
- {
- if (chip_data_size)
- limit_hunk ("chip data");
- else
- {
- chip_data = (uchar *) &file_ptr[1];
- chip_data_size = file_ptr[0] << 2;
- }
- }
- else
- {
- if (hdr.a_data)
- limit_hunk ("data");
- else
- {
- data = (uchar *)&file_ptr[1];
- hdr.a_data = file_ptr[0] << 2;
- }
- }
- }
- next_hunk (& file_ptr);
- add_table (is_chip ? & chip_data_hunks : & data_hunks, & hunk_num);
- hunk_num++;
- break;
-
- case HUNK_BSS:
- DP(("HUNK_BSS, size = $%x\n", file_ptr[0] << 2));
- is_chip = HUNK_ATTRIBUTE(file_ptr[-1]) == HUNK_ATTR_CHIP;
- if (file_ptr[0])
- {
- /* only accept one bss hunk with size != 0 */
- if (is_chip)
- {
- if (chip_bss_size)
- limit_hunk ("chip bss");
- else
- chip_bss_size = file_ptr[0] << 2;
- }
- else
- {
- if (hdr.a_bss)
- limit_hunk ("bss");
- else
- hdr.a_bss = file_ptr[0] << 2;
- }
- }
- file_ptr++;
- add_table (is_chip ? & chip_bss_hunks : & bss_hunks, & hunk_num);
- hunk_num++;
- break;
-
- case HUNK_RELOC8:
- case HUNK_RELOC16:
- case HUNK_RELOC32:
- /* do they work like this? don't know... */
- case HUNK_DREL8:
- case HUNK_DREL16:
- case HUNK_DREL32:
- {
- int size, brel;
-
- brel = file_ptr[-1] >= HUNK_DREL32;
- size = (brel ? HUNK_DREL8 : HUNK_RELOC8) - file_ptr[-1];
- DP(("HUNK_RELOC/DREL ($%x), brel = %d, size = %d\n", file_ptr[-1], brel, size));
-
- while (file_ptr[0])
- {
- long to_reloc = file_ptr[1];
- long n = file_ptr[0];
-
- while (n--)
- /* amiga relocs are automatically pcrel, when size < 2
- * according to the AmigaDOS-Manual 2nd ed. */
- add_reloc (&reloc_tab, hunk_num-1, to_reloc, file_ptr[n+2],
- size, size != 2, brel, -1);
-
- file_ptr += file_ptr[0] + 2;
- }
- }
- file_ptr++;
- break;
-
- case HUNK_SYMBOL:
- case HUNK_EXT:
- DP(("HUNK_SYMBOL/EXT\n"));
- while (file_ptr[0])
- {
- int n, size, brel;
-
- DP((" EXT_: %d, %-*.*s\n", file_ptr[0] >> 24,
- 4*(file_ptr[0] & 0xffffff), 4*(file_ptr[0] & 0xffffff), &file_ptr[1]));
-
- switch (file_ptr[0] >> 24)
- {
- case EXT_SYMB:
- case EXT_DEF:
- case EXT_ABS:
- case EXT_RES:
- add_symbol (&symbol_tab, hunk_num-1, file_ptr[0],
- file_ptr[1+(file_ptr[0] & 0xffffff)],
- (char *)&file_ptr[1]);
- file_ptr += 2+(file_ptr[0] & 0xffffff);
- break;
-
- case EXT_COMMON:
- /* first define the common symbol, then add the relocs */
- add_symbol (&symbol_tab, hunk_num-1, file_ptr[0],
- file_ptr[1+(file_ptr[0] & 0xffffff)],
- (char *)&file_ptr[1]);
- file_ptr += 2+(file_ptr[0] & 0xffffff);
-
- /* now the references, translated into relocs */
- for (n = file_ptr[0]; n--; )
- add_reloc (&reloc_tab, hunk_num - 1, -1, file_ptr[n],
- 2, 0, 0, symbol_tab.i - 1);
- next_hunk (&file_ptr);
- break;
-
- case EXT_REF8:
- case EXT_REF16:
- case EXT_REF32:
- case EXT_DEXT8:
- case EXT_DEXT16:
- case EXT_DEXT32:
- size = file_ptr[0] >> 24;
- brel = size >= EXT_DEXT32;
- size = (size == EXT_REF32 || size == EXT_DEXT32) ? 2 :
- ((size == EXT_REF16 || size == EXT_DEXT16) ? 1 : 0);
- /* first define the symbol (as undefined ;-)),
- * then add the relocs */
- add_symbol (&symbol_tab, hunk_num-1, file_ptr[0],
- 0, (char *)&file_ptr[1]);
- file_ptr += 1+(file_ptr[0] & 0xffffff);
-
- /* now the references, translated into relocs */
- for (n = file_ptr[0]; n; n--)
- add_reloc (&reloc_tab, hunk_num - 1, -1, file_ptr[n],
- size, size < 2, brel, symbol_tab.i - 1);
- next_hunk (&file_ptr);
- break;
-
- default:
- fprintf (stderr,
- "Unknown symbol type %d, don't know how to handle!\n",
- file_ptr[0] >> 24);
- /* can't continue, don't know how much to advance the file_ptr
- * to reach the next valid hunk/block */
- exit(20);
- }
- }
- file_ptr++;
- break;
-
- case HUNK_END:
- DP(("HUNK_END\n"));
- break;
-
- case HUNK_LIB:
- case HUNK_INDEX:
- fprintf (stderr, "Convert this library into ALINK (join type) format.\n");
- exit (20);
-
- default:
- fprintf (stderr, "Unknown hunk type $%x, unit offset = $%x.\n",
- file_ptr[-1], ((file_ptr-1)-*file_pptr) * 2);
- /* can't continue, don't know how much to advance the file_ptr
- * to reach the next valid hunk/block */
- exit(20);
- }
-
- if (file_ptr >= max_fp) break;
- }
-
- *file_pptr = file_ptr >= max_fp ? max_fp : file_ptr-1;
-
- if (fd != -1)
- emit_aout_file (fd, text, data, chip_data,
- & hdr, chip_data_size, chip_bss_size,
- & code_hunks, & data_hunks, & bss_hunks,
- & chip_data_hunks, & chip_bss_hunks,
- & reloc_tab, & symbol_tab, hunk_num);
- }
-
-
- void
- emit_aout_file (int fd, void *text, void *data, void *chip_data,
- struct exec *hdr, int chip_data_size, int chip_bss_size,
- struct table *ch_tab, struct table *dh_tab, struct table *bh_tab,
- struct table *cdh_tab, struct table *cbh_tab,
- struct table *reloc_tab, struct table *symbol_tab, int max_hunk)
- {
- int *code_hunks = ch_tab->base;
- int *data_hunks = dh_tab->base;
- int *bss_hunks = bh_tab->base;
- int *chip_data_hunks = cdh_tab->base;
- int *chip_bss_hunks = cbh_tab->base;
-
- char htype[max_hunk];
- int i;
- struct reloc *r;
- struct symbol *s;
- static struct table text_relocs = { 0, sizeof (struct relocation_info), 0, 0 };
- static struct table data_relocs = { 0, sizeof (struct relocation_info), 0, 0 };
-
- text_relocs.i =
- data_relocs.i = 0;
-
- /* convert hunk-numbers into N_TEXT,N_DATA,N_BSS types
- * I temporarily use N_EXT to really mean `N_CHIP'
- */
- for (i = 0; i < ch_tab->i; i++) htype[code_hunks[i]] = N_TEXT;
- for (i = 0; i < dh_tab->i; i++) htype[data_hunks[i]] = N_DATA;
- for (i = 0; i < bh_tab->i; i++) htype[bss_hunks[i]] = N_BSS;
- for (i = 0; i < cdh_tab->i; i++) htype[chip_data_hunks[i]] = N_DATA|N_EXT;
- for (i = 0; i < cbh_tab->i; i++) htype[chip_bss_hunks[i]] = N_BSS|N_EXT;
-
- #ifndef NDEBUG
- for (i = 0; i < max_hunk; i++) DP(("htype[%d] = %d\n", i, htype[i]));
- #endif
-
- /* first conversion run. Change all hunk-numbers into N_TEXT, N_DATA and
- * N_BSS rsp.
- * (If you wanted to support multi-hunk files (ie. files with more than
- * one code/data/bss hunk with size > 0) you'd want to do the necessary
- * conversions here.)
- * A less general solution is currently implemented: one chip data and one
- * chip bss hunk are supported as well. Multiple hunks should work analogous,
- * but with tables instead of variables like `chip_data_size' and `data'.
- */
- for (i = 0, r = (struct reloc *)reloc_tab->base; i < reloc_tab->i; i++, r++)
- {
- /* have to convert the destination hunk before the source hunk, since I
- * need the information, whether I have to change a data or a chip data
- * source. */
-
- /* Convert the destination hunk, if this is a local reloc. If it has
- * an associated symbol, that symbol will be converted from CHIP to whatever
- * is needed
- * If the target lies in a chip hunk, we have to change the offset in the
- * source hunk to include the `hunk-gap' between source and target
- */
- if (r->to_hunk > -1)
- {
- /* the base address of the used source hunk */
- void *base_hunk;
- /* this is the mentioned hunk-gap */
- ulong offset;
-
- switch (htype[r->from_hunk])
- {
- case N_TEXT:
- base_hunk = text;
- break;
-
- case N_DATA:
- base_hunk = data;
- break;
-
- case N_DATA|N_EXT:
- base_hunk = chip_data;
- break;
-
- default:
- fprintf (stderr, "Local reloc from illegal hunk ($%x)!\n",
- htype[r->from_hunk]);
- break;
- }
-
- /* account for an eventual shift of the former N_BSS space by
- * chip_data_size bytes */
- switch (htype[r->to_hunk])
- {
- /* those don't need a shift */
- case N_TEXT:
- case N_DATA:
- offset = 0;
- break;
-
- case N_BSS:
- offset = chip_data_size;
- break;
-
- case N_DATA|N_EXT:
- offset = hdr->a_data;
- break;
-
- case N_BSS|N_EXT:
- offset = chip_data_size + hdr->a_bss;
- break;
- }
-
- DP(("r->from = %d, r->to = %d, base = %d, offset = %d\n", r->from_hunk, r->to_hunk, htype[r->from_hunk], offset));
-
- /* I really don't know how much sense non-long relocs make here,
- * but it's easy to support, so .. ;-) */
- switch (r->size)
- {
- case 2:
- *(long *)(base_hunk + r->offset) += (long)offset;
- break;
-
- case 1:
- *(short *)(base_hunk + r->offset) += (short)offset;
- break;
-
- case 0:
- *(char *)(base_hunk + r->offset) += (char)offset;
- break;
- }
-
- r->to_hunk = htype[r->to_hunk] & ~N_EXT;
- }
-
- /* if it's a CHIP hunk, I have to increment the relocation address by
- * the size of the base hunk */
- if (htype[r->from_hunk] & N_EXT)
- {
- /* only N_DATA should come here, since there is no such thing as a
- * reloc originating from BSS space, but we nevertheless check for it.. */
- if (htype[r->from_hunk] == (N_DATA|N_EXT))
- r->offset += hdr->a_data;
- else
- fprintf (stderr, "Reloc from CHIP-BSS space, undefined!!\n");
- }
- r->from_hunk = htype[r->from_hunk] & ~N_EXT;
-
- }
-
-
- /* now convert the symbols into nlist's */
- for (i = 0, s = (struct symbol *)symbol_tab->base; i < symbol_tab->i; i++, s++)
- {
- int nl_type = 0;
-
- /* change hunk numbers into types */
- s->hunk_num = htype[s->hunk_num];
-
- switch (s->type)
- {
- case EXT_DEF:
- /* externally visible symbol */
- nl_type = N_EXT;
- /* fall into */
-
- case EXT_SYMB:
- nl_type |= s->hunk_num & ~N_EXT;
- /* adjust multi-hunk values to the one-seg model */
- if (s->hunk_num == N_DATA)
- s->value += hdr->a_text;
- else if (s->hunk_num == N_BSS)
- s->value += hdr->a_text + hdr->a_data + chip_data_size;
- else if (s->hunk_num == (N_DATA|N_EXT))
- s->value += hdr->a_text + hdr->a_data;
- else if (s->hunk_num == (N_BSS|N_EXT))
- s->value += hdr->a_text + hdr->a_data + chip_data_size + hdr->a_bss;
- break;
-
- case EXT_ABS:
- nl_type = N_ABS | N_EXT;
- break;
-
- case EXT_COMMON:
- /* ok for common as well, because the value field is only setup
- * for common-symbols */
-
- case EXT_REF32:
- case EXT_REF16:
- case EXT_REF8:
- case EXT_DEXT32:
- case EXT_DEXT16:
- case EXT_DEXT8:
- nl_type = N_UNDF | N_EXT;
- break;
-
- default:
- fprintf (stderr, "What kind of symbol is THAT? (%d)\n", s->type);
- break;
- }
-
- s->type = nl_type;
- s->pad1 = s->hunk_num = 0; /* clear nl_other & nl_desc fields */
- }
-
- /* now convert the reloc table. Adjust (like above) data/bss values to the
- * one-segment model for local relocations */
- for (i = 0, r = (struct reloc *)reloc_tab->base; i < reloc_tab->i; i++, r++)
- {
- struct relocation_info rel;
- uchar *core_addr;
- ulong delta;
-
- rel.r_address = r->offset;
- core_addr = (r->from_hunk == N_TEXT) ? text :
- ((r->offset < hdr->a_data) ? data : chip_data);
- /* r->offset has already been corrected to point at the chip data part
- * appended to the data part. Since we don't physically join these
- * segments (we just write them out after each other) we have to
- * ignore these changes for patches, this is what DELTA is used for. */
- delta = (core_addr == chip_data) ? hdr->a_data : 0;
-
- DP(("r_add = $%x, core = %s, delta = %d, ", rel.r_address,
- (core_addr == text) ? "text" : ((core_addr == data) ? "data" : "chip_data"),delta));
-
- if (r->to_hunk == N_DATA)
- if (r->size == 2)
- *(ulong *)(core_addr + rel.r_address - delta) += hdr->a_text;
- else
- fprintf (stderr, "%s reloc into N_DATA, what should I do?\n",
- r->size == 1 ? "Short" : "Byte");
- else if (r->to_hunk == N_BSS)
- if (r->size == 2)
- *(ulong *)(core_addr + rel.r_address - delta) += hdr->a_text + hdr->a_data;
- else
- fprintf (stderr, "%s reloc into N_BSS, what should I do?\n",
- r->size == 1 ? "Short" : "Byte");
-
- #if 0
- /* don't know, what went wrong, but this conversion surely converts
- * _LVO calls wrong. I'm sure leaving this out will generate other bugs..
- * sigh... */
-
-
- /* hmm... amigadog-hunks seem to do this in a strange way...
- * Those relocs *are* treated as pcrel relocs by the linker (blink),
- * but they're not setup as such... geez, this hunk format.. */
- if (r->pcrel)
- switch (r->size)
- {
- case 2:
- *(long *)(core_addr + rel.r_address - delta) -= rel.r_address;
- break;
-
- case 1:
- *(short *)(core_addr + rel.r_address - delta) -= (short)rel.r_address;
- break;
-
- case 0:
- *(char *)(core_addr + rel.r_address - delta) -= (char)rel.r_address;
- break;
- }
-
- #endif
-
- rel.r_symbolnum = r->sym_num > -1 ? r->sym_num : r->to_hunk;
- rel.r_pcrel = r->pcrel;
- rel.r_length = r->size;
- rel.r_extern = r->sym_num > -1;
- rel.r_baserel = r->baserel;
- rel.r_jmptable = /* rel.r_relative = */ 0;
-
- DP(("r68: %s reloc\n", (r->from_hunk == N_TEXT) ? "text" : "data"));
- add_table ((r->from_hunk == N_TEXT) ? & text_relocs : & data_relocs,
- &rel);
- }
-
- DP(("r68: #tr = %d, #dr = %d\n", text_relocs.i, data_relocs.i));
-
- /* depending on whether we had any actual CHIP data, we have to adjust
- * some of the header data, and we have to generate symbols containing the
- * real size of the non-chip section(s) */
- if (chip_data_size)
- {
- /* slightly different syntax, now that we directly add an nlist symbol */
- add_symbol (symbol_tab, 0, (N_ABS << 24) | ((sizeof (CHIP_DATA_START)+3)>>2),
- hdr->a_data, CHIP_DATA_START);
- hdr->a_data += chip_data_size;
- }
- if (chip_bss_size)
- {
- add_symbol (symbol_tab, 0, (N_ABS << 24) | ((sizeof (CHIP_BSS_START)+3)>>2),
- hdr->a_bss, CHIP_BSS_START);
- hdr->a_bss += chip_bss_size;
- }
-
- /* oky, fill out the rest of the header and dump everything */
- hdr->a_syms = symbol_tab->i * sizeof (struct nlist);
- hdr->a_trsize = text_relocs.i * sizeof (struct relocation_info);
- hdr->a_drsize = data_relocs.i * sizeof (struct relocation_info);
- *(ulong *)str_table = strtab_index;
- write (fd, (char *)hdr, sizeof (*hdr));
- if (hdr->a_text) write (fd, text, hdr->a_text);
- if (hdr->a_data - chip_data_size > 0)
- write (fd, data, hdr->a_data - chip_data_size);
- if (chip_data_size) write (fd, chip_data, chip_data_size);
- if (hdr->a_trsize) write (fd, text_relocs.base, hdr->a_trsize);
- if (hdr->a_drsize) write (fd, data_relocs.base, hdr->a_drsize);
- if (hdr->a_syms) write (fd, symbol_tab->base, hdr->a_syms);
- write (fd, str_table, strtab_index);
- close (fd);
- }
-
-
-
- int
- main (int argc, char *argv[])
- {
- struct stat stb;
- int ret_val = 0;
- ulong *obj_pointer;
-
- FILE *fp;
-
- /* loop over all arguments. Can be either
- * o object files
- * o libraries (ALINK style for now)
- */
- while (*++argv)
- {
- if (! strcmp (*argv, "-s"))
- {
- silent_mode = 1;
- continue;
- }
-
- if (stat (*argv, &stb) == -1)
- {
- fprintf (stderr, "%s: %s\n", *argv, strerror (errno));
- continue;
- }
-
- file_buf = file_buf ? realloc (file_buf, stb.st_size)
- : malloc (stb.st_size);
- if (! file_buf)
- {
- fprintf (stderr, "%s: can't allocate %d byte of memory.\n",
- *argv, stb.st_size);
- ret_val = 20;
- break;
- }
-
- if (!(fp = fopen (*argv, "r")))
- {
- fprintf (stderr, "Can't open %s: %s.\n", *argv, strerror (errno));
- continue;
- }
-
- /* read the file in at once */
- if (fread (file_buf, stb.st_size, 1, fp) != 1)
- {
- fprintf (stderr, "Can't read %s: %s.\n", *argv, strerror (errno));
- fclose (fp);
- continue;
- }
-
- if (! silent_mode)
- printf ("Converting %s:\n", *argv);
-
- /* oky, now digest the file (possibly more than one object file) */
- for (obj_pointer = file_buf;
- obj_pointer < (ulong *)((uchar *)file_buf + stb.st_size); )
- digest_objfile (&obj_pointer, (ulong *)((uchar *)file_buf + stb.st_size));
-
- if (! silent_mode)
- putchar ('\n');
-
- fclose (fp);
- }
-
- return ret_val;
- }
-