Initial OMF symbol support master
authorRobert Pengelly <robertapengelly@hotmail.com>
Tue, 29 Apr 2025 10:57:27 +0000 (11:57 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Tue, 29 Apr 2025 10:57:27 +0000 (11:57 +0100)
lib.c
lib.h
ranlib.c

diff --git a/lib.c b/lib.c
index aa774d898f53d3ac974aeb28472f2bbbb1b1d29a..aaf65d6bcb1034e8a7c8887954be4a71f82eb62b 100644 (file)
--- 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 d1adb091ca57a602af345f9713bce28e40b825f2..c8900eba4228422c79b0059eabedaeb36e9def1a 100644 (file)
--- 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);
index 5b813772af90032bd7b0a60ae9cefdf75af30dc6..15f6804e60b06a14af3a324ec275798da8e5a75b 100644 (file)
--- 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);