From d7262b53bed63d7c37dfe393e47fb9633ce615b6 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Mon, 7 Apr 2025 14:58:55 +0100 Subject: [PATCH] Support other object formats --- aout.h | 34 ++++++++ append.c | 2 +- coff.h | 34 ++++++++ conv.c | 13 ++- elf.h | 52 +++++++++++ ranlib.c | 262 +++++++++++++++++++++++++++++++++++++------------------ 6 files changed, 310 insertions(+), 87 deletions(-) create mode 100644 aout.h create mode 100644 coff.h create mode 100644 elf.h diff --git a/aout.h b/aout.h new file mode 100644 index 0000000..e5493b3 --- /dev/null +++ b/aout.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * @file aout.h + *****************************************************************************/ +#ifndef _AOUT_H +#define _AOUT_H + +struct aout_exec { + + unsigned char a_info[4]; + unsigned char a_text[4]; + unsigned char a_data[4]; + unsigned char a_bss[4]; + unsigned char a_syms[4]; + unsigned char a_entry[4]; + unsigned char a_trsize[4]; + unsigned char a_drsize[4]; + +}; + +#define AOUT_MAGIC 0407 + +struct aout_nlist { + + unsigned char n_strx[4]; + unsigned char n_type; + + unsigned char n_other; + unsigned char n_desc[2]; + + unsigned char n_value[4]; + +}; + +#endif /* _AOUT_H */ diff --git a/append.c b/append.c index 1389010..e27d5d8 100644 --- a/append.c +++ b/append.c @@ -32,7 +32,7 @@ void append (FILE *ofp, const char *fname) { memset (temp, ' ', 16); temp[0] = '0'; - if ((p = strrchr (fname, '/'))) { + if ((p = strrchr (fname, '/')) || (p = strrchr (fname, '\\'))) { name = (p + 1); } diff --git a/coff.h b/coff.h new file mode 100644 index 0000000..1c1c003 --- /dev/null +++ b/coff.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * @file coff.h + *****************************************************************************/ +#ifndef _COFF_H +#define _COFF_H + +struct coff_exec { + + unsigned char Machine[2]; + unsigned char NumberOfSections[2]; + + unsigned char TimeDateStamp[4]; + unsigned char PointerToSymbolTable[4]; + unsigned char NumberOfSymbols[4]; + + unsigned char SizeOfOptionalHeader[2]; + unsigned char Characteristics[2]; + +}; + +struct coff_symbol { + + char Name[8]; + unsigned char Value[4]; + + unsigned char SectionNumber[2]; + unsigned char Type[2]; + + unsigned char StorageClass[1]; + unsigned char NumberOfAuxSymbols[1]; + +}; + +#endif /* _COFF_H */ diff --git a/conv.c b/conv.c index 459194b..88c8c28 100644 --- a/conv.c +++ b/conv.c @@ -6,11 +6,18 @@ unsigned long conv_dec (char *str, long max) { unsigned long value = 0; + char ch; - while (*str != ' ' && max-- > 0) { + while ((ch = *str)) { - value *= 10; - value += *str++ - '0'; + if (ch == ' ' || max == 0) { + break; + } + + value = ((value * 10) + (ch - '0')); + + str++; + max--; } diff --git a/elf.h b/elf.h new file mode 100644 index 0000000..5ff7b69 --- /dev/null +++ b/elf.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * @file coff.h + *****************************************************************************/ +#ifndef _ELF_H +#define _ELF_H + +struct elf_exec { + + unsigned char e_ident[16]; + unsigned char e_type[2]; + unsigned char e_machine[2]; + unsigned char e_version[4]; + unsigned char e_entry[4]; + unsigned char e_phoff[4]; + unsigned char e_shoff[4]; + unsigned char e_flags[4]; + unsigned char e_ehsize[2]; + unsigned char e_phentsize[2]; + unsigned char e_phnum[2]; + unsigned char e_shentsize[2]; + unsigned char e_shnum[2]; + unsigned char e_shstrndx[2]; + +}; + +struct elf_shdr { + + unsigned char sh_name[4]; + unsigned char sh_type[4]; + unsigned char sh_flags[4]; + unsigned char sh_addr[4]; + unsigned char sh_offset[4]; + unsigned char sh_size[4]; + unsigned char sh_link[4]; + unsigned char sh_info[4]; + unsigned char sh_addralign[4]; + unsigned char sh_entsize[4]; + +}; + +struct elf_sym { + + unsigned char st_name[4]; + unsigned char st_value[4]; + unsigned char st_size[4]; + unsigned char st_info[1]; + unsigned char st_other[1]; + unsigned char st_shndx[2]; + +}; + +#endif /* _ELF_H */ diff --git a/ranlib.c b/ranlib.c index 415062f..d510c58 100644 --- a/ranlib.c +++ b/ranlib.c @@ -7,46 +7,18 @@ #include #include +#include "aout.h" #include "ar.h" +#include "coff.h" +#include "elf.h" #include "elks.h" #include "lib.h" #include "report.h" -#if INT_MAX == 32767 -typedef signed long int32_t; -#else -typedef signed int int32_t; -#endif - #define GET_INT32(arr) ((long) arr[0] | (((long) arr[1]) << 8) | (((long) arr[2]) << 16) | (((long) arr[3]) << 24)) - -#define GET_UINT16(arr) ((unsigned long) arr[0] | (((unsigned long) arr[1]) << 8)) #define GET_UINT32(arr) ((unsigned long) arr[0] | (((unsigned long) arr[1]) << 8) | (((unsigned long) arr[2]) << 16) | (((unsigned long) arr[3]) << 24)) -/*struct aout_exec { - - unsigned char a_info[4]; - unsigned char a_text[4]; - unsigned char a_data[4]; - unsigned char a_bss[4]; - unsigned char a_syms[4]; - unsigned char a_entry[4]; - unsigned char a_trsize[4]; - unsigned char a_drsize[4]; - -}; - -struct aout_nlist { - - unsigned char n_strx[4]; - unsigned char n_type; - - unsigned char n_other; - unsigned char n_desc[2]; - - unsigned char n_value[4]; - -};*/ +#define GET_UINT16(arr) ((unsigned long) arr[0] | (((unsigned long) arr[1]) << 8)) struct strtab { @@ -95,64 +67,39 @@ static int add_strtab (struct gstrtab *gstrtab, struct strtab *strtab) { } -/*static void aout_get_symbols (void *object, long offset) { +static void aout_get_symbols (void *object, long offset) { struct aout_exec *hdr = (struct aout_exec *) object; long sym_start = sizeof (*hdr) + GET_UINT32 (hdr->a_text) + GET_UINT32 (hdr->a_data) + GET_UINT32 (hdr->a_trsize) + GET_UINT32 (hdr->a_drsize); long strtab_start = sym_start + GET_UINT32 (hdr->a_syms); + struct strtab *strtab; + struct aout_nlist nlist; + while (sym_start < strtab_start) { - if (hdr->a_info[0] == 0x07) { - - struct aout_nlist nlist; - memcpy (&nlist, (char *) object + sym_start, sizeof (nlist)); - - if (nlist.n_type == 5 || nlist.n_type == 7 || nlist.n_type == 9) { - - struct strtab *strtab; - char *symname = (char *) object + strtab_start + GET_INT32 (nlist.n_strx); - - strtab = xmalloc (sizeof (*strtab)); - strtab->length = strlen (symname); - - strtab->name = xstrdup (symname); - strtab->offset = offset; - - add_strtab (&gstrtab, strtab); - - } - - sym_start += sizeof (nlist); + memcpy (&nlist, (char *) object + sym_start, sizeof (nlist)); - } else { + if (nlist.n_type == 5 || nlist.n_type == 7 || nlist.n_type == 9) { - struct nlist nlist; - memcpy (&nlist, (char *) object + sym_start, sizeof (nlist)); - - if (nlist.n_type == 5 || nlist.n_type == 7 || nlist.n_type == 9) { + char *symname = (char *) object + strtab_start + GET_INT32 (nlist.n_strx); - struct strtab *strtab; - char *symname = (char *) object + strtab_start + GET_INT32 (nlist.n_strx); - - strtab = xmalloc (sizeof (*strtab)); - strtab->length = strlen (symname); - - strtab->name = xstrdup (symname); - strtab->offset = offset; - - add_strtab (&gstrtab, strtab); + strtab = xmalloc (sizeof (*strtab)); + strtab->length = strlen (symname); - } + strtab->name = xstrdup (symname); + strtab->offset = offset; - sym_start += sizeof (nlist); + add_strtab (&gstrtab, strtab); } + + sym_start += sizeof (nlist); } -}*/ +} static void elks_get_symbols (void *object, long offset) { @@ -161,6 +108,7 @@ static void elks_get_symbols (void *object, long offset) { long sym_start = sizeof (*hdr) + GET_UINT32 (hdr->a_text) + GET_UINT32 (hdr->a_data) + GET_UINT32 (hdr->a_trsize) + GET_UINT32 (hdr->a_drsize); long strtab_start = sym_start + GET_UINT32 (hdr->a_syms); + struct strtab *strtab; struct elks_nlist nlist; while (sym_start < strtab_start) { @@ -169,7 +117,6 @@ static void elks_get_symbols (void *object, long offset) { if (nlist.n_type == 5 || nlist.n_type == 7 || nlist.n_type == 9) { - struct strtab *strtab; char *symname = (char *) object + strtab_start + GET_INT32 (nlist.n_strx); strtab = xmalloc (sizeof (*strtab)); @@ -188,12 +135,163 @@ static void elks_get_symbols (void *object, long offset) { } +static void coff_get_symbols (void *object, long offset) { + + struct coff_exec *hdr = (struct coff_exec *) object; + + unsigned long sym_start = GET_UINT32 (hdr->PointerToSymbolTable); + unsigned long sym_cnt = GET_UINT32 (hdr->NumberOfSymbols); + unsigned long string_table_start = sym_start + (sizeof (struct coff_symbol) * sym_cnt); + + struct coff_symbol sym; + + while (sym_cnt--) { + + memcpy (&sym, (char *) object + sym_start, sizeof (sym)); + + if (sym.StorageClass[0] == 2 && GET_UINT16 (sym.SectionNumber) != 0) { + + struct strtab *strtab; + + if (sym.Name[0] != 0) { + + int i, len; + + for (i = 0, len = 0; i < 8; i++) { + + if (sym.Name[i] == '\0') { + break; + } + + len++; + + } + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = len; + + strtab->name = xstrdup (sym.Name); + strtab->offset = offset; + + add_strtab (&gstrtab, strtab); + + } else { + + unsigned char offset1 = (unsigned char) sym.Name[4]; + unsigned char offset2 = (unsigned char) sym.Name[5]; + unsigned char offset3 = (unsigned char) sym.Name[6]; + unsigned char offset4 = (unsigned char) sym.Name[7]; + + long final_offset = (((long) offset1) | (((long) offset2) << 8) | (((long) offset3) << 16) | (((long) offset4) << 24)); + final_offset += string_table_start; + + strtab = xmalloc (sizeof (*strtab)); + strtab->length = strlen ((char *) object + final_offset); + + strtab->name = xstrdup ((char *) object + final_offset); + strtab->offset = offset; + + add_strtab (&gstrtab, strtab); + + } + + } + + sym_start += sizeof (sym); + + } + +} + +#define GET_ELF_UINT16(arr) (endianess ? (((unsigned long) arr[0] << 8) | (((unsigned long) arr[1]))) : ((unsigned long) arr[0] | (((unsigned long) arr[1]) << 8))) + +#define GET_ELF_UINT32(arr) (endianess ? (((unsigned long) arr[0] << 24) | (((unsigned long) arr[1]) << 16) | (((unsigned long) arr[2]) << 8) | (((unsigned long) arr[3]))) \ + : ((unsigned long) arr[0] | (((unsigned long) arr[1]) << 8) | (((unsigned long) arr[2]) << 16) | (((unsigned long) arr[3]) << 24))) + +static void elf_get_symbols (void *object, long offset, int endianess) { + + struct elf_exec *hdr = (struct elf_exec *) object; + + unsigned long e_shnum = GET_ELF_UINT16 (hdr->e_shnum); + unsigned long e_shoff = GET_ELF_UINT32 (hdr->e_shoff); + unsigned long e_shentsize = GET_ELF_UINT16 (hdr->e_shentsize); + + unsigned long sh_link, sh_offset, sh_entsize, sh_size; + unsigned long sym_strtab_size, i, j, st_name; + + struct elf_shdr strtabhdr; + struct elf_shdr shdr; + struct elf_sym elf_symbol; + + struct strtab *strtab; + char *sym_strtab; + + for (i = 1; i < e_shnum; i++) { + + memcpy (&shdr, (char *) object + e_shoff + i * e_shentsize, sizeof (shdr)); + + if (GET_ELF_UINT32 (shdr.sh_type) != 2) { + continue; + } + + sh_link = GET_ELF_UINT32 (shdr.sh_link); + sh_offset = GET_ELF_UINT32 (shdr.sh_offset); + + if (sh_link == 0 || sh_link >= e_shnum) { + continue; + } + + memcpy (&strtabhdr, (char *) object + e_shoff + sh_link * e_shentsize, sizeof (strtabhdr)); + + if (GET_ELF_UINT32 (strtabhdr.sh_type) != 3) { + continue; + } + + sym_strtab_size = GET_ELF_UINT32 (strtabhdr.sh_size); + sym_strtab = (char *) object + GET_ELF_UINT32 (strtabhdr.sh_offset); + + if ((sh_entsize = GET_ELF_UINT32 (shdr.sh_entsize)) < sizeof (elf_symbol)) { + continue; + } + + sh_size = GET_ELF_UINT32 (shdr.sh_size); + + for (j = 1; j < sh_size / sh_entsize; j++) { + + memcpy (&elf_symbol, (char *) object + sh_offset + j * sh_entsize, sizeof (elf_symbol)); + + if ((st_name = GET_ELF_UINT32 (elf_symbol.st_name)) >= sym_strtab_size) { + continue; + } + + if (GET_ELF_UINT16 (elf_symbol.st_shndx) == 0 || (elf_symbol.st_info[0] >> 4) != 1) { + continue; + } + + if (sym_strtab[st_name] != '\0') { + + strtab = xmalloc (sizeof (*strtab)); + strtab->offset = offset; + + strtab->name = xstrdup (sym_strtab + st_name); + strtab->length = strlen (strtab->name); + + add_strtab (&gstrtab, strtab); + + } + + } + + } + +} + void ranlib (FILE *arfp) { FILE *tfp = tmpfile (); struct ar_header header; - int32_t bytes, i, j, len, read, val; + long bytes, i, j, len, read, val; unsigned char *object; void *contents; @@ -242,12 +340,14 @@ void ranlib (FILE *arfp) { } - /*if ((object[0] == 0x39 || object[0] == 0x07) && object[1] == 0x01 && object[2] == 0x64 && object[3] == 0x00) { - aout_get_symbols (object, offset + 8); - }*/ - - if (object[0] == ((ELKS_MAGIC >> 8) & 0xff) && object[1] == (ELKS_MAGIC & 0xff)) { + if (object[0] == 0x01 && object[1] == 0x03) { elks_get_symbols (object, offset + 8); + } else if (object[0] == 0x07 && object[1] == 0x01) { + aout_get_symbols (object, offset + 8); + } else if ((object[0] == 0x4C && object[1] == 0x01) || (object[0] == 0x64 && object[1] == 0x86)) { + coff_get_symbols (object, offset + 8); + } else if (object[0] == 0x7F && memcmp (object + 1, "ELF", 3) == 0) { + elf_get_symbols (object, offset + 8, object[5] == 2); } free (object); @@ -298,11 +398,7 @@ void ranlib (FILE *arfp) { memcpy (header.group, temp, 6); memcpy (header.mode, temp, 8); -#if INT_MAX == 32767 len = sprintf (temp, "%ld", bytes + 4); -#else - len = sprintf (temp, "%d", bytes + 4); -#endif temp[len] = ' '; memcpy (header.size, temp, 10); -- 2.34.1