From: Robert Pengelly Date: Tue, 29 Apr 2025 10:57:27 +0000 (+0100) Subject: Initial OMF symbol support X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=45b0426d345d530f793f6689ecb598d027b721f6;p=xar.git Initial OMF symbol support --- diff --git a/lib.c b/lib.c index aa774d8..aaf65d6 100644 --- a/lib.c +++ b/lib.c @@ -45,6 +45,28 @@ char *xstrdup (const char *str) { } +char *xstrndup (const char *__p, unsigned long __size) { + + char *p = xmalloc (__size + 1); + + memcpy (p, __p, __size); + return p; + +} + +unsigned long array_to_integer (unsigned char *arr, int size) { + + unsigned long value = 0; + int i; + + for (i = 0; i < size; i++) { + value |= arr[i] << (CHAR_BIT * i); + } + + return value; + +} + void *xmalloc (unsigned long size) { void *ptr = malloc (size); diff --git a/lib.h b/lib.h index d1adb09..c8900eb 100644 --- a/lib.h +++ b/lib.h @@ -5,6 +5,9 @@ #define _LIB_H char *xstrdup (const char *str); +char *xstrndup (const char *__p, unsigned long __size); + +unsigned long array_to_integer (unsigned char *arr, int size); void *xmalloc (unsigned long size); void *xrealloc (void *ptr, unsigned long size); diff --git a/ranlib.c b/ranlib.c index 5b81377..15f6804 100644 --- a/ranlib.c +++ b/ranlib.c @@ -343,6 +343,122 @@ static void elf_get_symbols (void *object, long offset, int endianess) { } +#define RECORD_TYPE_EXTDEF 0x8C +#define RECORD_TYPE_PUBDEF 0x90 + +static void omf_get_symbols (void *object, char *filename, unsigned long bytes, long offset) { + + unsigned char *pos = (unsigned char *) object; + + unsigned char record_type; + unsigned short record_len; + + unsigned char *pubdef_name, *pubdef_name_end; + unsigned char pubdef_name_len; + + unsigned char *extdef_name, *extdef_name_end; + unsigned char extdef_name_len; + + struct strtab *strtab; + int big_fields; + + while (pos < (unsigned char *) object + bytes) { + + record_type = pos[0]; + + big_fields = record_type & 1; + record_type &= ~1; + + record_len = array_to_integer (pos + 1, 2); + + { + + unsigned char checksum = 0; + unsigned long i; + + for (i = 0; i < (unsigned long) record_len + 3; i++) { + checksum += pos[i]; + } + + if (checksum != 0) { + report_at (program_name, 0, REPORT_WARNING, "%s: invalid checksum", filename); + } + + } + + pos += 3; + + if (record_type == RECORD_TYPE_EXTDEF) { + + extdef_name_end = (extdef_name = pos) + record_len - 1; + + while (extdef_name != extdef_name_end) { + + extdef_name_len = extdef_name[0]; + + if (extdef_name + 1 + extdef_name_len + 1 > extdef_name_end) { + + report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: incorrect string length", filename); + exit (EXIT_FAILURE); + + } + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = extdef_name_len; + + strtab->name = xstrndup ((char *) extdef_name + 1, extdef_name_len); + strtab->offset = offset; + + /*report_at (program_name, 0, REPORT_WARNING, "Got length of %#x for %s", extdef_name_len, strtab->name);*/ + + add_strtab (&gstrtab, strtab); + extdef_name = extdef_name + 1 + extdef_name_len + 1; + + } + + } else if (record_type == RECORD_TYPE_PUBDEF) { + + pubdef_name_end = (pubdef_name = pos) + record_len - 3; + + if (big_fields) { + + report_at (program_name, 0, REPORT_INTERNAL_ERROR, "%s: big fields not supported for record %#x", filename, record_type); + exit (EXIT_FAILURE); + + } + + while (pubdef_name != pubdef_name_end) { + + pubdef_name_len = pubdef_name[2]; + + if (pubdef_name + 2 + 1 + pubdef_name_len + 1 > pubdef_name_end) { + + report_at (program_name, 0, REPORT_FATAL_ERROR, "%s: incorrect string length", filename); + exit (EXIT_FAILURE); + + } + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = pubdef_name_len; + + strtab->name = xstrndup ((char *) pubdef_name + 3, pubdef_name_len); + strtab->offset = offset; + + /*report_at (program_name, 0, REPORT_WARNING, "Got length of %#x for %s", pubdef_name_len, strtab->name);*/ + + add_strtab (&gstrtab, strtab); + pubdef_name = pubdef_name + 2 + 1 + pubdef_name_len + 1; + + } + + } + + pos += record_len; + + } + +} + void ranlib (void) { FILE *tfp = tmpfile (); @@ -355,12 +471,11 @@ void ranlib (void) { void *contents; char temp[16]; - /*int valid = 0;*/ for (;;) { struct ar_header hdr; - long bytes; + long bytes, real_size; if (fread (&hdr, sizeof (hdr), 1, arfp) != 1) { @@ -374,6 +489,7 @@ void ranlib (void) { } bytes = conv_dec (hdr.size, 10); + real_size = bytes; if (bytes % 2) { bytes++; @@ -398,20 +514,6 @@ void ranlib (void) { } - /*valid = ((object[0] == 0x07 && object[1] == 0x01) || (object[0] == 0x4C && object[1] == 0x01) || (object[0] == 0x64 && object[1] == 0x86)); - - if (!valid) { - - free (object); - - offset += sizeof (hdr); - offset += bytes; - - fseek (arfp, bytes, SEEK_CUR); - continue; - - }*/ - if (object[0] == 0x07 && object[1] == 0x01) { aout_get_symbols (object, offset + 8); @@ -453,6 +555,29 @@ void ranlib (void) { } + if (object[0] == 0x80 /* RECORD_TYPE_THEADR */) { + + char filename[17] = { 0 }; + memcpy (filename, hdr.name, 16); + + for (i = 16; i >= 0; --i) { + + if (filename[i] == ' ') { + filename[i] = '\0'; + } + + } + + omf_get_symbols (object, filename, real_size, offset + 8); + free (object); + + offset += sizeof (hdr); + offset += bytes; + + continue; + + } + free (object); offset += sizeof (hdr);