Support other object formats
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 7 Apr 2025 13:58:55 +0000 (14:58 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 7 Apr 2025 13:58:55 +0000 (14:58 +0100)
aout.h [new file with mode: 0644]
append.c
coff.h [new file with mode: 0644]
conv.c
elf.h [new file with mode: 0644]
ranlib.c

diff --git a/aout.h b/aout.h
new file mode 100644 (file)
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 */
index 1389010fdf7ab83e8d30a963a4c7eb9366dd7f2c..e27d5d8c66e347bbfcc8f9e32dfafb18645eb3cd 100644 (file)
--- 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 (file)
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 459194b461376f249ff49fdf1efe58d929c8f033..88c8c281f93a39ac46ae4c704b6de3bb9a8b24ea 100644 (file)
--- 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 (file)
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 */
index 415062ffbc8fa917961aa73320aea79a8dd0b782..d510c58784ed830b8ef6e5ed674b7c311b940636 100644 (file)
--- a/ranlib.c
+++ b/ranlib.c
@@ -7,46 +7,18 @@
 #include    <stdlib.h>
 #include    <string.h>
 
+#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);