Generate Mach-O symbols master
authorRobert Pengelly <robertapengelly@hotmail.com>
Tue, 28 Oct 2025 19:09:03 +0000 (19:09 +0000)
committerRobert Pengelly <robertapengelly@hotmail.com>
Tue, 28 Oct 2025 19:09:03 +0000 (19:09 +0000)
macho.h [new file with mode: 0644]
ranlib.c

diff --git a/macho.h b/macho.h
new file mode 100644 (file)
index 0000000..3225e89
--- /dev/null
+++ b/macho.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * @file            macho.h
+ *****************************************************************************/
+#ifndef     _MACHO_H
+#define     _MACHO_H
+
+struct macho_header_64 {
+
+    unsigned char magic[4];
+    unsigned char cpu_type[4];
+    unsigned char cpu_subtype[4];
+    unsigned char file_type[4];
+    unsigned char num_cmds[4];
+    unsigned char sizeof_cmds[4];
+    unsigned char flags[4];
+    unsigned char reserved[4];
+
+};
+
+#define     MH_MAGIC_64                 0xFEEDFACF
+
+#define     MH_CPU_TYPE_AMD64           0x01000007
+#define     MH_CPU_TYPE_ARM64           0x0100000C
+
+#define     MH_CPU_SUBTYPE_I386_ALL     3
+#define     MH_OBJECT                   1
+
+struct load_command {
+
+    unsigned char command[4];
+    unsigned char command_size[4];
+
+};
+
+#define     LC_SEGMENT_64               0x19
+#define     LC_SYMTAB                   0x02
+
+struct segment_command_64 {
+
+    unsigned char command[4];
+    unsigned char command_size[4];
+    
+    char seg_name[16];
+    
+    unsigned char vm_addr[8];
+    unsigned char vm_size[8];
+    unsigned char file_off[8];
+    unsigned char file_size[8];
+    
+    unsigned char max_prot[4];
+    unsigned char init_prot[4];
+    unsigned char num_sects[4];
+    unsigned char flags[4];
+
+};
+
+struct section_64 {
+
+    char sect_name[16];
+    char seg_name[16];
+    
+    unsigned char addr[8];
+    unsigned char size[8];
+    
+    unsigned char offset[4];
+    unsigned char align[4];
+    unsigned char rel_off[4];
+    unsigned char num_reloc[4];
+    
+    unsigned char flags[4];
+    
+    unsigned char reserved1[4];
+    unsigned char reserved2[4];
+    unsigned char reserved3[4];
+
+};
+
+struct symtab_command {
+
+    unsigned char command[4];
+    unsigned char command_size[4];
+    unsigned char symbol_offset[4];
+    unsigned char num_symbols[4];
+    unsigned char string_offset[4];
+    unsigned char string_size[4];
+
+};
+
+#define     MACHO_N_EXT                 0x01
+
+struct nlist_64 {
+
+    unsigned char n_strx[4];
+    unsigned char n_type[1];
+    unsigned char n_sect[1];
+    unsigned char n_desc[2];
+    unsigned char n_value[8];
+
+};
+
+#endif      /* _MACHO_H */
index 61eec684520e907df739a6c0f3ff58559ea95423..7b26ca527207c5c60ea3ab47e4d199d176b8c4a9 100644 (file)
--- a/ranlib.c
+++ b/ranlib.c
@@ -13,6 +13,7 @@
 #include    "elf.h"
 #include    "elks.h"
 #include    "lib.h"
+#include    "macho.h"
 #include    "report.h"
 #include    "stdint.h"
 
@@ -505,6 +506,96 @@ static void hunk_get_symbols (void *object, uint64_t bytes, int64_t offset) {
 
 }
 
+static void macho_get_symbols (void *object, int64_t offset) {
+
+    unsigned char *pos = (unsigned char *) object;
+    
+    struct macho_header_64 *header;
+    struct strtab *strtab;
+    
+    struct symtab_command *symtab_cmd;
+    struct load_command *load_command;
+    
+    unsigned long cpu_type, num_commands, num_syms;
+    unsigned long i, j;
+    
+    unsigned char *sym_pos;
+    char *string_table, *symbol_name;
+    
+    struct nlist_64 *nlist_64;
+    unsigned long n_strx;
+    
+    header = (struct macho_header_64 *) pos;
+    pos += sizeof (*header);
+    
+    cpu_type = array_to_integer (header->cpu_type, 4, 0);
+    
+    if (cpu_type != MH_CPU_TYPE_AMD64 && cpu_type != MH_CPU_TYPE_ARM64) {
+        return;
+    }
+    
+    if (array_to_integer (header->file_type, 4, 0) != MH_OBJECT) {
+        return;
+    }
+    
+    num_commands = array_to_integer (header->num_cmds, 4, 0);
+    
+    for (i = 0; i < num_commands; i++) {
+    
+        load_command = (struct load_command *) pos;
+        
+        if (array_to_integer (load_command->command, 4, 0) == LC_SYMTAB) {
+        
+            symtab_cmd = (struct symtab_command *) pos;
+            
+            if (!(num_syms = array_to_integer (symtab_cmd->num_symbols, 4, 0))) {
+            
+                pos += array_to_integer (load_command->command_size, 4, 0);
+                continue;
+            
+            }
+            
+            string_table = (char *) object + array_to_integer (symtab_cmd->string_offset, 4, 0);
+            sym_pos = (unsigned char *) object + array_to_integer (symtab_cmd->symbol_offset, 4, 0);
+            
+            for (j = 0; j < num_syms; j++) {
+            
+                nlist_64 = (struct nlist_64 *) (sym_pos + j * sizeof (*nlist_64));
+                
+                if ((n_strx = array_to_integer (nlist_64->n_strx, 4, 0)) < array_to_integer (symtab_cmd->string_size, 4, 0)) {
+                
+                    if (string_table[n_strx] != '\0') {
+                    
+                        symbol_name = xstrdup (string_table + n_strx);
+                        
+                        if (nlist_64->n_type[0] & MACHO_N_EXT) {
+                        
+                            strtab = xmalloc (sizeof (*strtab));
+                            strtab->offset = offset;
+                            
+                            strtab->name = symbol_name;
+                            strtab->length = strlen (strtab->name);
+                            
+                            add_strtab (&gstrtab, strtab);
+                        
+                        }
+                    
+                    }
+                
+                }
+            
+            }
+            
+            break;
+        
+        }
+        
+        pos += array_to_integer (load_command->command_size, 4, 0);
+    
+    }
+
+}
+
 #define     RECORD_TYPE_EXTDEF          0x8C
 #define     RECORD_TYPE_PUBDEF          0x90
 
@@ -693,13 +784,15 @@ void ranlib (FILE *arfp) {
         } else if (object[0] == 0x7F && memcmp (object + 1, "ELF", 3) == 0) {
         
             int endianess = (object[5] == 2);
-
+            
             if (object[4] == 2) {
                 elf64_get_symbols (object, offset + 8, endianess);
             } else {
                 elf32_get_symbols (object, offset + 8, endianess);
             }
         
+        } else if (object[0] == 0xCF && object[1] == 0xFA && object[2] == 0xED && object[3] == 0xFE) {
+            macho_get_symbols (object, offset + 8);
         } else if (object[0] == 0x80) {
         
             char filename[17] = { 0 };