This is NeXT-exec.m in view mode; [Download] [Up]
#import "gdb.h" #import <fcntl.h> #import "loadSymbols.h" #import "objfiles.h" #import <sys/stat.h> #import "TellDisplayer.h" typedef struct _ManagerChain { SegmentManager *manager; CORE_ADDR jmpTableStart; CORE_ADDR jmpTableEnd; CORE_ADDR dyldTableStart; CORE_ADDR dyldTableEnd; struct _ManagerChain *next; } ManagerChain; static ManagerChain *execManagers = NULL; SegmentManager *execManager = NULL; extern struct target_ops exec_ops; extern void addLoadedObjectModule (struct objfile *obj); extern struct objfile * symfile_add (); int isShlibJump(address) CORE_ADDR address; { ManagerChain *mChain; for (mChain = execManagers; mChain; mChain = mChain->next) { if ((mChain->jmpTableStart <= address) && (address < mChain->jmpTableEnd)) return YES; } return NO; } int isDylibJump(address) CORE_ADDR address; { ManagerChain *mChain; for (mChain = execManagers; mChain; mChain = mChain->next) { if ((mChain->dyldTableStart <= address) && (address < mChain->dyldTableEnd)) return YES; } return NO; } static void initExecManager(mChain) ManagerChain *mChain; { const struct section *firstSection; SegmentManager *manager = mChain->manager; const struct section *sec; /* first see if it is a static shared library */ if ([manager isShlib] && (firstSection = [manager firstSection])) { mChain->jmpTableStart = firstSection->addr; mChain->jmpTableEnd = jmpTableEnd(((void *)[manager getMachHeader]) + firstSection->offset, firstSection); } else { /* no, not a static shlib */ mChain->jmpTableStart = 0xFFFFFFFF; mChain->jmpTableEnd = 0x0; /* now see if it is a dynamic shared library */ if (!(sec = [manager getSeg: "__TEXT" sect: "__picsymbol_stub"])) sec = [manager getSeg: "__TEXT" sect: "__symbol_stub"]; if (sec) { /* found (pic)symbol_stub */ mChain->dyldTableStart = sec->addr + [manager getSlide]; mChain->dyldTableEnd = sec->size + mChain->dyldTableStart; } else { /* no, not a dynamic shlib */ mChain->dyldTableStart = 0xFFFFFFFF; mChain->dyldTableEnd = 0x0; } } readObjC(manager); } void addExecManager(manager) SegmentManager *manager; { ManagerChain *mChain; if (execManagers) { for (mChain = execManagers; mChain->next; mChain = mChain->next); mChain->next = malloc(sizeof(*mChain)); mChain = mChain->next; } else { execManagers = mChain = malloc(sizeof(*mChain)); execManager = manager; } mChain->manager = manager; mChain->next = NULL; initExecManager(mChain); } void invalidateExecManager(manager) SegmentManager *manager; { removeObjC(manager); clear_value_history (); clear_displays (); clear_internalvars (); set_default_breakpoint (0, 0, 0, 0); current_source_symtab = 0; innermost_block = 0; } void removeExecManager(manager) SegmentManager *manager; { invalidateExecManager(manager); if (execManagers) { ManagerChain *mChain; for (mChain = execManagers; mChain && (mChain->next->manager != manager); mChain = mChain->next); if (mChain) { ManagerChain *oldChain = mChain->next; mChain->next = oldChain->next; free(oldChain); } } } void execFileAddShlibs(manager) SegmentManager *manager; { struct mach_header *header = [manager getMachHeader]; int nCmds; struct load_command *loadCmd; char *name, *originalName; SegmentManager *shlibManager; if ([manager isExecutable]) { for (nCmds = header->ncmds, loadCmd = (struct load_command *)(header + 1); nCmds; nCmds--, ((void *)loadCmd) += loadCmd->cmdsize) { if (loadCmd->cmd == LC_LOADFVMLIB) { name = (char *) getShlibName((struct fvmlib_command *)loadCmd, &originalName); if (originalName) printf("Aliasing %s to %s...\n", originalName, name); shlibManager = [SegmentManager newShlib: name cpuType: cpuType()]; if (shlibManager) addExecManager(shlibManager); else error("Could not open `%s' as a shlib.", name); } } } } SegmentManager *execFileAdd(name, desc) char *name; int desc; { SegmentManager *manager = [SegmentManager newExecutable: name skipShlibs: YES withDesc: desc cpuType: cpuType()]; ManagerChain *mChain; if (!manager) error("Could not open `%s' as an executable file.", name); addExecManager(manager); execFileAddShlibs(manager); validate_files (); return manager; } /* Process the first arg in ARGS as the new exec file. Note that we have to explicitly ignore additional args, since we can be called from file_command(), which also calls symbol_file_command() which can take multiple args. */ void exec_file_command(args, from_tty) char *args; int from_tty; { char **argv; char *filename; target_preopen (from_tty); /* Remove any previous exec file. */ unpush_target (&exec_ops); /* Now open and digest the file the user requested, if any. */ if (args) { char *scratch_pathname; int scratch_chan; /* Scan through the args and pick up the first non option arg as the filename. */ if ((argv = buildargv(args)) == NULL) { nomem(0); } make_cleanup(freeargv, (char *)argv); for (; (*argv != NULL) && (**argv == '-'); argv++) {;} if (*argv == NULL) { error ("no exec file name was specified"); } filename = tilde_expand(*argv); make_cleanup(free, filename); scratch_chan = openp(getenv("PATH"), 1, filename, O_RDONLY, 0, &scratch_pathname); if (scratch_chan < 0) perror_with_name(filename); execFileAdd(scratch_pathname, scratch_chan); push_target (&exec_ops); tell_displayer_state_changed(DBG_STATE_INFERIOR_LOADED); } else if (from_tty) printf ("No exec file now.\n"); } static void exec_close(quitting) { if (execManager) execManager = [execManager free]; } static int exec_xfer_memory (memaddr, myaddr, len, write, target) CORE_ADDR memaddr; char *myaddr; int len, write; struct target_ops *target; { ManagerChain *mChain; int bytesRead = 0; if (write) error("Can't write to executable files."); for (mChain = execManagers; mChain && !bytesRead; mChain = mChain->next) { bytesRead = [mChain->manager getDataAt: (void *)memaddr for: len into: myaddr]; } return bytesRead; } static void NeXT_add_file(args, from_tty) char *args; int from_tty; { char *name; CORE_ADDR text_addr = 0; dont_repeat (); if (args == 0) error ("add-symbol-file takes a file name and an optional address"); args = tilde_expand (args); make_cleanup (free, args); for(; *args == ' '; args++ ); name = args; for(; *args && *args != ' ' ; args++ ); if (*args) { LoadInfo loadInfo; char *theNames[] = {name, NULL}; *args++ = '\0'; loadInfo.headerAddr = (struct mach_header *)parse_and_eval_address(args); loadSymbolsForInfo(&loadInfo, theNames); } else { SegmentManager *manager = execFileAdd(name, -1); symfile_add(manager, 0, 0, 0, 0, 0); } tell_displayer_state_changed(DBG_STATE_INFERIOR_LOADED); } static void NeXT_add_module(args, from_tty) char *args; int from_tty; { CORE_ADDR header_addr = 0, vm_slide = 0; SegmentManager *manager = 0; char *next_arg; struct mach_header* header; dont_repeat (); if (args == 0) { error ("add-module takes an address and an optional vmslide"); return; } args = tilde_expand (args); make_cleanup (free, args); while (*args == ' ') args++; for (next_arg = args; *next_arg && *next_arg != ' '; next_arg++) ; if (*next_arg == ' ') *next_arg++ = 0; else *next_arg = 0; header_addr = (CORE_ADDR) parse_and_eval_address (args); header = WARP ((struct mach_header*)header_addr); if (header == 0) { error ("address %p not a valid address", header_addr); return; } if (header->magic != MH_MAGIC && header->magic != MH_CIGAM) { error ("address %p not a valid header", header_addr); return; } if (*next_arg) vm_slide = (CORE_ADDR) parse_and_eval_address (next_arg); else { if (header->filetype == MH_DYLIB || header->filetype == MH_DYLINKER) vm_slide = header_addr; else vm_slide = 0; } if (from_tty) { switch (header->filetype) { case MH_DYLIB: printf ("Dynamic Shared Library"); break; case MH_DYLINKER: printf ("Dynamic Linkeditor"); break; case MH_FVMLIB: printf ("Fixed Virtual Memory Shared Library"); break; case MH_PRELOAD: printf ("Preloaded Executable"); break; case MH_EXECUTE: printf ("Executable"); break; default: printf ("Object Module"); } printf (" at 0x%x offset 0x%x\n", header_addr, vm_slide); } if (header->filetype == MH_DYLINKER) { struct stat buf; static vm_offset_t pos = 0; if (pos == 0) { int fd, i; struct load_command *cmd; char *name = "/usr/lib/dyld"; for (cmd = (struct load_command *)(header + 1), i = 0; i < header->ncmds; ((void *)cmd) += cmd->cmdsize, i++) { if (cmd->cmd == LC_ID_DYLINKER) { struct dylinker_command* dylCmd = (struct dylinker_command*) cmd; name = (char*) cmd + ((struct dylinker_command*) cmd)->name.offset; break; } } fd = open ("/usr/lib/dyld", O_RDONLY); fstat (fd, &buf); map_fd (fd, 0, &pos, 1, buf.st_size); } manager = [SegmentManager newHeader: (struct mach_header*)pos withSlide: vm_slide]; addExecManager(manager); addLoadedObjectModule (symfile_add(manager, 0, vm_slide, 0, 0, 0)); } else { header = [regionManager copyLoadedImage:(struct mach_header*) header_addr withSlide:vm_slide]; manager = [SegmentManager newHeader:header withSlide:0]; addExecManager(manager); addLoadedObjectModule (symfile_add (manager, 0, 0, 0, 0, 0)); } } /* Return the name of the executable file as a string. ERR nonzero means get error if there is none specified; otherwise return 0 in that case. */ char * get_exec_file(err) { if (execManager) return [execManager executableName]; else if (err) error("No executable file specified.\n" "Use the \"file\" or \"exec-file\" command."); else return NULL; } void file_command (arg, from_tty) char *arg; int from_tty; { /* FIXME, if we lose on reading the symbol file, we should revert the exec file, but that's rough. */ exec_file_command (arg, from_tty); symbol_file_command (arg, from_tty); } void reread_exec() { struct objfile *obj, *foundObj = NULL; struct stat buf; int res; ManagerChain *mChain; if (execManagers) { for (mChain = execManagers; mChain; mChain = mChain->next) { res = stat([mChain->manager executableName], &buf); if (res == 0) { if (buf.st_mtime != [mChain->manager mtime]) { printf("'%s' has changed, rereading symbols.\n", [mChain->manager executableName]); invalidateExecManager(mChain->manager); [mChain->manager invalidate]; [mChain->manager getImages]; [mChain->manager readInAllRelocs]; initExecManager(mChain); for (obj = object_files; obj && !foundObj; obj = obj->next) { if (obj->manager == mChain->manager) foundObj = obj; } if (foundObj) free_objfile(foundObj); symfile_add(mChain->manager, 0, 0, 0, 0, 0); } } } } } void check_executables(args, from_tty) char *args; int from_tty; { reread_exec(); } void no_file_command(args, from_tty) char *args; int from_tty; { /* watch out -- ANSI string merging */ printf("Commands symbol-file, exec-file, and file are no longer supported.\n" "Use the update-files command to force rereading of any files " "which have changed.\n"); } struct target_ops exec_ops = { "exec", /* to_shortname */ "Local exec file", /* to_longname */ "Use an executable file as a target.\n" "Specify the filename of the executable file.", /* to_doc */ exec_file_command, /* to_open */ exec_close, /* to_close */ find_default_attach, /* to_attach */ 0, /* to_detach */ 0, /* to_resume */ 0, /* to_wait */ 0, /* to_fetch_registers */ 0, /* to_store_registers */ 0, /* to_prepare_to_store */ exec_xfer_memory, /* to_xfer_memory */ 0, /* to_files_info */ 0, /* to_insert_breakpoint */ 0, /* to_remove_breakpoint */ 0, /* to_terminal_init */ 0, /* to_terminal_inferior */ 0, /* to_terminal_ours_for_output */ 0, /* to_terminal_ours */ 0, /* to_terminal_info */ 0, /* to_kill */ 0, /* to_load */ 0, /* to_lookup_symbol */ find_default_create_inferior, /* to_create_inferior */ 0, /* to_mourn_inferior */ 0, /* to_can_run */ 0, /* to_notice_signals */ 0, /* to_stop */ file_stratum, /* to_stratum */ 0, /* DONT_USE (formerly to_next) */ 0, /* to_has_all_memory */ 1, /* to_has_memory */ 0, /* to_has_stack */ 0, /* to_has_registers */ 0, /* to_has_execution */ 0, /* sections */ 0, /* sections_end */ OPS_MAGIC /* to_magic */ }; void _initialize_nextexec () { add_com ("add-file", class_files, NeXT_add_file, "Load the symbols from FILE, assuming FILE has been dynamically loaded.\n" "If a second argument is provided it indicates the starting address of\n" "the file's text.\n" "Otherwise the file is assumed to be the debug output file as produced by\n" "rld_load or objc_loadModules.\n"); add_com ("add-module", class_files, NeXT_add_module, "Register the module with mach-o header ADDR, and optional\n" "vmslide SLIDE as a module in the current program. This will\n" "enable debugging of that particular module."); add_com ("update-files", class_files, check_executables, "Reread any symbol files which have changed."); add_com ("file", class_files, no_file_command, "No longer supported. Use update-files command to force rereading of any changed symbol files."); add_com ("exec-file", class_files, no_file_command, "No longer supported. Use update-files command to force rereading of any changed symbol files."); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.