[darwinbuild-changes] [305] trunk/darwinxref
source_changes at macosforge.org
source_changes at macosforge.org
Wed Oct 4 02:02:30 PDT 2006
Revision: 305
http://trac.macosforge.org/projects/darwinbuild/changeset/305
Author: kevin
Date: 2006-10-04 02:02:30 -0700 (Wed, 04 Oct 2006)
Log Message:
-----------
- register mach-o symbols
Modified Paths:
--------------
trunk/darwinxref/Makefile
trunk/darwinxref/plugins/register.c
Modified: trunk/darwinxref/Makefile
===================================================================
--- trunk/darwinxref/Makefile 2005-11-30 00:58:38 UTC (rev 304)
+++ trunk/darwinxref/Makefile 2006-10-04 09:02:30 UTC (rev 305)
@@ -76,7 +76,7 @@
$(SQLITELIB)
plugins/register.so: plugins/register.c DBPlugin.h
- cc -o $@ $(PLUGIN_CFLAGS) $(PLUGIN_LDFLAGS) -lcrypto $<
+ cc -o $@ $(PLUGIN_CFLAGS) $(PLUGIN_LDFLAGS) $(SQLITEINC) $(SQLITELIB) -lcrypto $<
plugins/%.so: plugins/%.c DBPlugin.h
cc -o $@ $(PLUGIN_CFLAGS) $(PLUGIN_LDFLAGS) $<
Modified: trunk/darwinxref/plugins/register.c
===================================================================
--- trunk/darwinxref/plugins/register.c 2005-11-30 00:58:38 UTC (rev 304)
+++ trunk/darwinxref/plugins/register.c 2006-10-04 09:02:30 UTC (rev 305)
@@ -43,6 +43,7 @@
#include <unistd.h>
#include <string.h>
#include <openssl/evp.h>
+#include "sqlite3.h"
extern char** environ;
@@ -243,8 +244,67 @@
mh->reserved = NXSwapLong(mh->reserved);
}
+static void
+swap_segment_command_64(
+struct segment_command_64* sg,
+enum NXByteOrder target_byte_sex)
+{
+ /* char segname[16] */
+ sg->cmd = NXSwapLong(sg->cmd);
+ sg->cmdsize = NXSwapLong(sg->cmdsize);
+ sg->vmaddr = NXSwapLongLong(sg->vmaddr);
+ sg->vmsize = NXSwapLongLong(sg->vmsize);
+ sg->fileoff = NXSwapLongLong(sg->fileoff);
+ sg->filesize = NXSwapLongLong(sg->filesize);
+ sg->maxprot = NXSwapLong(sg->maxprot);
+ sg->initprot = NXSwapLong(sg->initprot);
+ sg->nsects = NXSwapLong(sg->nsects);
+ sg->flags = NXSwapLong(sg->flags);
+}
-static int register_mach_header(char* build, char* project, int fd, int* isMachO) {
+static void
+swap_section_64(
+struct section_64 *s,
+uint32_t nsects,
+enum NXByteOrder target_byte_sex)
+{
+ uint32_t i;
+
+ for(i = 0; i < nsects; i++){
+ /* sectname[16] */
+ /* segname[16] */
+ s[i].addr = NXSwapLongLong(s[i].addr);
+ s[i].size = NXSwapLongLong(s[i].size);
+ s[i].offset = NXSwapLong(s[i].offset);
+ s[i].align = NXSwapLong(s[i].align);
+ s[i].reloff = NXSwapLong(s[i].reloff);
+ s[i].nreloc = NXSwapLong(s[i].nreloc);
+ s[i].flags = NXSwapLong(s[i].flags);
+ s[i].reserved1 = NXSwapLong(s[i].reserved1);
+ s[i].reserved2 = NXSwapLong(s[i].reserved2);
+ s[i].reserved3 = NXSwapLong(s[i].reserved3);
+ }
+}
+
+static void
+swap_nlist_64(
+struct nlist_64 *symbols,
+uint32_t nsymbols,
+enum NXByteOrder target_byte_sex)
+{
+ uint32_t i;
+
+ for(i = 0; i < nsymbols; i++){
+ symbols[i].n_un.n_strx = NXSwapLong(symbols[i].n_un.n_strx);
+ /* n_type */
+ /* n_sect */
+ symbols[i].n_desc = NXSwapShort(symbols[i].n_desc);
+ symbols[i].n_value = NXSwapLongLong(symbols[i].n_value);
+ }
+}
+
+
+static int register_mach_header(const char* build, const char* project, const char* path, struct fat_arch* fa, int fd, int* isMachO) {
int res;
uint32_t magic;
int swap = 0;
@@ -294,7 +354,7 @@
return 0;
}
-
+
switch (mh->filetype) {
case MH_EXECUTE:
case MH_DYLIB:
@@ -304,7 +364,31 @@
default:
return 0;
}
+
+ res = SQL("INSERT INTO mach_o_objects (magic, type, cputype, cpusubtype, flags, build, project, path) VALUES (%u, %u, %u, %u, %u, %Q, %Q, %Q)",
+ mh64 ? mh64->magic : mh->magic,
+ mh64 ? mh64->filetype : mh->filetype,
+ mh64 ? mh64->cputype : mh->cputype,
+ mh64 ? mh64->cpusubtype : mh->cpusubtype,
+ mh64 ? mh64->flags : mh->flags,
+ build, project, path);
+ uint64_t serial = sqlite3_last_insert_rowid((sqlite3*)_DBPluginGetDataStorePtr());
+
+ //
+ // Information needed to parse the symbol table
+ //
+ int count_nsect = 0;
+ unsigned char text_nsect = NO_SECT;
+ unsigned char data_nsect = NO_SECT;
+ unsigned char bss_nsect = NO_SECT;
+
+ uint32_t nsyms = 0;
+ uint8_t *symbols = NULL;
+ uint32_t strsize = 0;
+ uint8_t *strings = NULL;
+
+
int i;
for (i = 0; i < mh->ncmds; ++i) {
//
@@ -329,6 +413,10 @@
res = read(fd, (uint8_t*)lc + sizeof(struct load_command), cmdsize - sizeof(struct load_command));
if (res < (cmdsize - sizeof(struct load_command))) { free(lc); return 0; }
+ //
+ // LC_LOAD_DYLIB and LC_LOAD_WEAK_DYLIB
+ // Add dylibs as unresolved "lib" dependencies.
+ //
if (cmd == LC_LOAD_DYLIB || cmd == LC_LOAD_WEAK_DYLIB) {
struct dylib_command *dylib = (struct dylib_command*)lc;
if (swap) swap_dylib_command(dylib, NXHostByteOrder());
@@ -346,6 +434,10 @@
free(str);
+ //
+ // LC_LOAD_DYLINKER
+ // Add the dynamic linker (usually dyld) as an unresolved "lib" dependency.
+ //
} else if (cmd == LC_LOAD_DYLINKER) {
struct dylinker_command *dylinker = (struct dylinker_command*)lc;
if (swap) swap_dylinker_command(dylinker, NXHostByteOrder());
@@ -362,23 +454,166 @@
build, project, "lib", str);
free(str);
+
+ //
+ // LC_SYMTAB
+ // Read the symbol table into memory, we'll process it after we're
+ // done with the load commands.
+ //
+ } else if (cmd == LC_SYMTAB && symbols == NULL) {
+ struct symtab_command *symtab = (struct symtab_command*)lc;
+ if (swap) swap_symtab_command(symtab, NXHostByteOrder());
+
+ nsyms = symtab->nsyms;
+ uint32_t symsize = nsyms * sizeof(struct nlist); // XXX: nlist_64
+ symbols = malloc(symsize);
+
+ strsize = symtab->strsize;
+ // XXX: check strsize != 0
+ strings = malloc(strsize);
+
+ off_t save = lseek(fd, 0, SEEK_CUR);
+
+ off_t origin = fa ? fa->offset : 0;
+
+ lseek(fd, symtab->symoff + origin, SEEK_SET);
+ res = read(fd, symbols, symsize);
+ if (res < symsize) { /* XXX: leaks */ return 0; }
+
+ lseek(fd, symtab->stroff + origin, SEEK_SET);
+ res = read(fd, strings, strsize);
+ if (res < strsize) { /* XXX: leaks */ return 0; }
+
+ lseek(fd, save, SEEK_SET);
+
+ //
+ // LC_SEGMENT
+ // We're looking for the section number of the text, data, and bss segments
+ // in order to parse symbols.
+ //
+ } else if (cmd == LC_SEGMENT) {
+ struct segment_command* seg = (struct segment_command*)lc;
+ if (swap) swap_segment_command(seg, NXHostByteOrder());
+
+ // sections immediately follow the segment_command structure, and are
+ // reflected in the cmdsize.
+ int k;
+ for (k = 0; k < seg->nsects; ++k) {
+ struct section* sect = (struct section*)((uint8_t*)seg + sizeof(struct segment_command) + k * sizeof(struct section));
+ if (strcmp(sect->sectname, SECT_TEXT) == 0 && strcmp(sect->segname, SEG_TEXT) == 0) {
+ text_nsect = ++count_nsect;
+ } else if (strcmp(sect->sectname, SECT_DATA) == 0 && strcmp(sect->segname, SEG_DATA) == 0) {
+ data_nsect = ++count_nsect;
+ } else if (strcmp(sect->sectname, SECT_BSS) == 0 && strcmp(sect->segname, SEG_DATA) == 0) {
+ bss_nsect = ++count_nsect;
+ } else {
+ ++count_nsect;
+ }
+ }
+
+ //
+ // LC_SEGMENT_64
+ // Same as LC_SEGMENT, but for 64-bit binaries.
+ //
+ } else if (lc->cmd == LC_SEGMENT_64) {
+ struct segment_command_64* seg = (struct segment_command_64*)lc;
+ if (swap) swap_segment_command_64(seg, NXHostByteOrder());
+
+ // sections immediately follow the segment_command structure, and are
+ // reflected in the cmdsize.
+ int k;
+ for (k = 0; k < seg->nsects; ++k) {
+ struct section_64* sect = (struct section_64*)((uint8_t*)seg + sizeof(struct segment_command_64) + k * sizeof(struct section_64));
+ if (strcmp(sect->sectname, SECT_TEXT) == 0 && strcmp(sect->segname, SEG_TEXT) == 0) {
+ text_nsect = ++count_nsect;
+ } else if (strcmp(sect->sectname, SECT_DATA) == 0 && strcmp(sect->segname, SEG_DATA) == 0) {
+ data_nsect = ++count_nsect;
+ } else if (strcmp(sect->sectname, SECT_BSS) == 0 && strcmp(sect->segname, SEG_DATA) == 0) {
+ bss_nsect = ++count_nsect;
+ } else {
+ ++count_nsect;
+ }
+ }
}
free(lc);
}
+ //
+ // Finished processing the load commands, now insert symbols into the database.
+ //
+ int j;
+ for (j = 0; j < nsyms; ++j) {
+ struct nlist_64 symbol;
+ if (mh64) {
+ memcpy(&symbol, (symbols + j * sizeof(struct nlist_64)), sizeof(struct nlist_64));
+ if (swap) swap_nlist_64(&symbol, 1, NXHostByteOrder());
+ } else {
+ memcpy(&symbol, (symbols + j * sizeof(struct nlist)), sizeof(struct nlist));
+ if (swap) swap_nlist_64(&symbol, 1, NXHostByteOrder());
+ // we copied a 32-bit nlist into a 64-bit one, adjust the value accordingly
+ // all other fields are identical sizes
+ symbol.n_value >>= 32;
+ }
+ char type = '?';
+ switch (symbol.n_type & N_TYPE) {
+ case N_UNDF:
+ case N_PBUD:
+ type = 'u';
+ if (symbol.n_value != 0) {
+ type = 'c';
+ }
+ break;
+ case N_ABS:
+ type = 'a';
+ break;
+ case N_SECT:
+ if (symbol.n_sect == text_nsect) {
+ type = 't';
+ } else if (symbol.n_sect == data_nsect) {
+ type = 'd';
+ } else if (symbol.n_sect == bss_nsect) {
+ type = 'b';
+ } else {
+ type = 's';
+ }
+ break;
+ case N_INDR:
+ type = 'i';
+ break;
+ }
+
+ // uppercase indicates an externally visible symbol
+ if ((symbol.n_type & N_EXT) && type != '?') {
+ type = toupper(type);
+ }
+
+ if (type != '?' && type != 'u' && type != 'c') {
+ const uint8_t* name = (const uint8_t*)"";
+ if (symbol.n_un.n_strx != 0) {
+ name = (uint8_t*)(strings + symbol.n_un.n_strx);
+ }
+ res = SQL("INSERT INTO mach_o_symbols VALUES (%lld, %u, %lld, %Q)",
+ serial,
+ type,
+ symbol.n_value,
+ name);
+ }
+ }
+
return 0;
}
-static int register_libraries(int fd, char* build, char* project, int* isMachO) {
+static int register_libraries(int fd, const char* build, const char* project, const char* filename, int* isMachO) {
int res;
+ SQL("DELETE FROM mach_o_objects WHERE build=%Q AND project=%Q AND path=%Q;", build, project, filename);
+
uint32_t magic;
res = read(fd, &magic, sizeof(uint32_t));
if (res < sizeof(uint32_t)) { goto error_out; }
- // It's a fat file. copy mh over to fh, and dereference.
if (magic == FAT_MAGIC || magic == FAT_CIGAM) {
struct fat_header fh;
int swap = 0;
@@ -390,7 +625,7 @@
swap = 1;
swap_fat_header(&fh, NXHostByteOrder());
}
-
+
int i;
for (i = 0; i < fh.nfat_arch; ++i) {
struct fat_arch fa;
@@ -402,13 +637,13 @@
off_t save = lseek(fd, 0, SEEK_CUR);
lseek(fd, (off_t)fa.offset, SEEK_SET);
- register_mach_header(build, project, fd, isMachO);
+ register_mach_header(build, project, filename, &fa, fd, isMachO);
lseek(fd, save, SEEK_SET);
}
} else {
lseek(fd, 0, SEEK_SET);
- register_mach_header(build, project, fd, isMachO);
+ register_mach_header(build, project, filename, NULL, fd, isMachO);
}
error_out:
return 0;
@@ -424,8 +659,15 @@
char* index = "CREATE INDEX files_index ON files (build, project, path)";
SQL_NOERR(table);
SQL_NOERR(index);
+
table = "CREATE TABLE unresolved_dependencies (build text, project text, type text, dependency)";
SQL_NOERR(table);
+
+ table = "CREATE TABLE mach_o_objects (serial INTEGER PRIMARY KEY AUTOINCREMENT, magic INTEGER, type INTEGER, cputype INTEGER, cpusubtype INTEGER, flags INTEGER, build TEXT, project TEXT, path TEXT)";
+ SQL_NOERR(table);
+
+ table = "CREATE TABLE mach_o_symbols (mach_o_object INTEGER, type INTEGER, value INTEGER, name TEXT)";
+ SQL_NOERR(table);
if (SQL("BEGIN")) { return -1; }
@@ -473,7 +715,7 @@
return -1;
}
int isMachO;
- res = register_libraries(fd, build, project, &isMachO);
+ res = register_libraries(fd, build, project, filename, &isMachO);
lseek(fd, (off_t)0, SEEK_SET);
if (isMachO && have_undo_prebinding() == 0) {
checksum = calculate_unprebound_digest(ent->fts_accpath);
@@ -589,7 +831,7 @@
perror(filename);
return -1;
}
- res = register_libraries(fd, build, project, NULL);
+ res = register_libraries(fd, build, project, filename, NULL);
/* For -stdin mode, we don't calculate checksums
lseek(fd, (off_t)0, SEEK_SET);
checksum = calculate_digest(fd);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20061004/ff580044/attachment-0001.html
More information about the darwinbuild-changes
mailing list