diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/minsyms.c | 30 | ||||
-rw-r--r-- | gdb/rs6000-tdep.c | 38 | ||||
-rw-r--r-- | gdb/rs6000-xdep.c | 2 | ||||
-rw-r--r-- | gdb/xcoffexec.c | 224 | ||||
-rw-r--r-- | gdb/xcoffread.c | 184 |
5 files changed, 388 insertions, 90 deletions
diff --git a/gdb/minsyms.c b/gdb/minsyms.c index a1df5b6..9367204 100644 --- a/gdb/minsyms.c +++ b/gdb/minsyms.c @@ -116,7 +116,7 @@ iterate_over_msymbols (func, arg1, arg2, arg3) particular objfile and the search is limited to that objfile. Returns a pointer to the minimal symbol that matches, or NULL if no match is found. - Note: One instance where their may be duplicate minimal symbols with + Note: One instance where there may be duplicate minimal symbols with the same name is when the symbol tables for a shared library and the symbol tables for an executable contain global symbols with the same names (the dynamic linker deals with the duplication). */ @@ -129,6 +129,9 @@ lookup_minimal_symbol (name, objf) struct objfile *objfile; struct minimal_symbol *msymbol; struct minimal_symbol *found_symbol = NULL; +#ifdef IBM6000 + struct minimal_symbol *trampoline_symbol = NULL; +#endif for (objfile = object_files; objfile != NULL && found_symbol == NULL; @@ -143,11 +146,36 @@ lookup_minimal_symbol (name, objf) { if (strcmp (msymbol -> name, name) == 0) { +/* I *think* all platforms using shared libraries (and trampoline code) + * will suffer this problem. Consider a case where there are 5 shared + * libraries, each referencing `foo' with a trampoline entry. When someone + * wants to put a breakpoint on `foo' and the only info we have is minimal + * symbol vector, we want to use the real `foo', rather than one of those + * trampoline entries. MGO */ +#ifdef IBM6000 + /* If a trampoline symbol is found, we prefer to keep looking + for the *real* symbol. If the actual symbol not found, + then we'll use the trampoline entry. Sorry for the machine + dependent code here, but I hope this will benefit other + platforms as well. For trampoline entries, we used mst_unknown + earlier. Perhaps we should define a `mst_trampoline' type?? */ + + if (msymbol->type != mst_unknown) + found_symbol = msymbol; + else if (msymbol->type == mst_unknown && !trampoline_symbol) + trampoline_symbol = msymbol; + +#else found_symbol = msymbol; +#endif } } } } +#ifdef IBM6000 + return found_symbol ? found_symbol : trampoline_symbol; +#endif + return (found_symbol); } diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index e64e378..297e77d 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -44,6 +44,7 @@ extern int attach_flag; /* Nonzero if we just simulated a single step break. */ int one_stepped; + /* Breakpoint shadows for the single step instructions will be kept here. */ static struct sstep_breaks { @@ -188,13 +189,6 @@ int pc; op = read_memory_integer (pc, 4); } -#if 0 - if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */ - pc += 4; /* store floating register double */ - op = read_memory_integer (pc, 4); - } -#endif - if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */ pc += 4; op = read_memory_integer (pc, 4); @@ -213,7 +207,7 @@ int pc; op = read_memory_integer (pc, 4); } - /* store parameters into stack */ + /* store parameters into stack */ while( (op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */ (op & 0xfc1f0000) == 0x90010000 || /* st r?, NUM(r1) */ @@ -235,6 +229,33 @@ int pc; tmp += 0x20; } } +#if 0 +/* I have problems with skipping over __main() that I need to address + * sometime. Previously, I used to use misc_function_vector which + * didn't work as well as I wanted to be. -MGO */ + + /* If the first thing after skipping a prolog is a branch to a function, + this might be a call to an initializer in main(), introduced by gcc2. + We'd like to skip over it as well. Fortunately, xlc does some extra + work before calling a function right after a prologue, thus we can + single out such gcc2 behaviour. */ + + + if ((op & 0xfc000001) == 0x48000001) { /* bl foo, an initializer function? */ + op = read_memory_integer (pc+4, 4); + + if (op == 0x4def7b82) { /* cror 0xf, 0xf, 0xf (nop) */ + + /* check and see if we are in main. If so, skip over this initializer + function as well. */ + + tmp = find_pc_misc_function (pc); + if (tmp >= 0 && !strcmp (misc_function_vector [tmp].name, "main")) + return pc + 8; + } + } +#endif /* 0 */ + return pc; } @@ -244,6 +265,7 @@ int pc; CORE_ADDR text_start; CORE_ADDR text_end; + /************************************************************************* Support for creating pushind a dummy frame into the stack, and popping frames, etc. diff --git a/gdb/rs6000-xdep.c b/gdb/rs6000-xdep.c index 62f3f59..c8c0c1d 100644 --- a/gdb/rs6000-xdep.c +++ b/gdb/rs6000-xdep.c @@ -333,7 +333,7 @@ frame_initial_stack_address (fi) return fi->initial_sp = read_register (fdata.alloca_reg); /* Otherwise, this is a caller frame. Callee has usually already saved - registers, but there are are exceptions (such as when the callee + registers, but there are exceptions (such as when the callee has no parameters). Find the address in which caller's alloca register is saved. */ diff --git a/gdb/xcoffexec.c b/gdb/xcoffexec.c index 4e45a75..31d5825 100644 --- a/gdb/xcoffexec.c +++ b/gdb/xcoffexec.c @@ -124,7 +124,16 @@ exec_close(quitting) } vmap = 0; - exec_bfd = 0; + + if (exec_bfd) { + bfd_close (exec_bfd); + exec_bfd = NULL; + } + if (exec_ops.to_sections) { + free (exec_ops.to_sections); + exec_ops.to_sections = NULL; + exec_ops.to_sections_end = NULL; + } } /* @@ -134,9 +143,9 @@ void exec_file_command(filename, from_tty) char *filename; { - bfd *bfd; - target_preopen(from_tty); + + /* Remove any previous exec file. */ unpush_target(&exec_ops); /* Now open and digest the file the user requested, if any. */ @@ -148,33 +157,33 @@ char *filename; filename = tilde_expand(filename); make_cleanup (free, filename); - scratch_chan = openp(getenv("PATH"), 1, filename, O_RDONLY, 0 - , &scratch_pathname); + scratch_chan = openp(getenv("PATH"), 1, filename, + write_files? O_RDWR: O_RDONLY, 0, + &scratch_pathname); if (scratch_chan < 0) perror_with_name(filename); - bfd = bfd_fdopenr(scratch_pathname, NULL, scratch_chan); - if (!bfd) + exec_bfd = bfd_fdopenr(scratch_pathname, NULL, scratch_chan); + if (!exec_bfd) error("Could not open `%s' as an executable file: %s" , scratch_pathname, bfd_errmsg(bfd_error)); /* make sure we have an object file */ - if (!bfd_check_format(bfd, bfd_object)) - error("\"%s\": not in executable format: %s." - , scratch_pathname, bfd_errmsg(bfd_error)); + if (!bfd_check_format(exec_bfd, bfd_object)) + error("\"%s\": not in executable format: %s.", + scratch_pathname, bfd_errmsg(bfd_error)); /* setup initial vmap */ - map_vmap (bfd, 0); + map_vmap (exec_bfd, 0); if (!vmap) - error("Can't find the file sections in `%s': %s" - , bfd->filename, bfd_errmsg(bfd_error)); - - exec_bfd = bfd; + error("Can't find the file sections in `%s': %s", + exec_bfd->filename, bfd_errmsg(bfd_error)); - if (build_section_table (exec_bfd, &exec_sections, &exec_sections_end)) + if (build_section_table (exec_bfd, &exec_ops.to_sections, + &exec_ops.to_sections_end)) error ("Can't find the file sections in `%s': %s", exec_bfd->filename, bfd_errmsg (bfd_error)); @@ -224,6 +233,9 @@ add_to_section_table (abfd, asect, table_pp_char) /* FIXME, we need to handle BSS segment here...it alloc's but doesn't load */ if (!(aflag & SEC_LOAD)) return; + if (0 == bfd_section_size (abfd, asect)) + return; + (*table_pp)->bfd = abfd; (*table_pp)->sec_ptr = asect; (*table_pp)->addr = bfd_section_vma (abfd, asect); (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect); @@ -280,12 +292,12 @@ sex_to_vmap(bfd *bf, sec_ptr sex, struct vmap_and_bfd *vmap_bfd) vp->tstart = 0; vp->tend = vp->tstart + bfd_section_size(bf, sex); - /* This is quite a tacky way to recognize the `exec' load segment (rather - than shared libraries. You should use `arch' instead. FIXMEmgo */ - if (!vmap) - vp->tadj = sex->filepos - bfd_section_vma(bf, sex); - else - vp->tadj = 0; + /* When it comes to this adjustment value, in contrast to our previous + belief shared objects should behave the same as the main load segment. + This is the offset from the beginning of text section to the first + real instruction. */ + + vp->tadj = sex->filepos - bfd_section_vma(bf, sex); } else if (!strcmp(bfd_section_name(bf, sex), ".data")) { @@ -328,9 +340,33 @@ map_vmap (bfd *bf, bfd *arch) *vpp = vp; } + +#define FASTER_MSYMBOL_RELOCATION 1 + +#ifdef FASTER_MSYMBOL_RELOCATION + +/* Used to relocate an object file's minimal symbols. */ + +static void +reloc_objfile_msymbols (objf, addr) +struct objfile *objf; +CORE_ADDR addr; +{ + register struct minimal_symbol *msymbol; + int ii; + + for (msymbol = objf->msymbols, ii=0; + msymbol && ii < objf->minimal_symbol_count; ++msymbol, ++ii) + + if (msymbol->address < TEXT_SEGMENT_BASE) + msymbol->address += addr; +} + +#else /* !FASTER_MSYMBOL_RELOCATION */ + /* Called via iterate_over_msymbols to relocate minimal symbols */ -static PTR +static int relocate_minimal_symbol (objfile, msymbol, arg1, arg2, arg3) struct objfile *objfile; struct minimal_symbol *msymbol; @@ -340,8 +376,12 @@ relocate_minimal_symbol (objfile, msymbol, arg1, arg2, arg3) { if (msymbol->address < TEXT_SEGMENT_BASE) msymbol -> address += (int) arg1; - return (NULL); + + /* return 0, otherwise `iterate_over_msymbols()' will stop at the + first iteration. */ + return 0; } +#endif /* FASTER_MSYMBOL_RELOCATION */ /* true, if symbol table and minimal symbol table are relocated. */ @@ -400,14 +440,34 @@ struct stat *vip; continue; } - if (vp->tstart != old_start) - vmap_symtab_1(s, vp, old_start); + if (vp->tstart != old_start) { + + /* Once we find a relocation base address for one of the symtabs + in this objfile, it will be the same for all symtabs in this + objfile. Clean this algorithm. FIXME. */ + + for (; s; s = s->next) + if (!s->nonreloc || LINETABLE(s)) + vmap_symtab_1(s, vp, old_start); + +#ifdef FASTER_MSYMBOL_RELOCATION + /* we can rely on the fact that at least one symtab in this objfile + will get relocated. Thus, we can be sure that minimal symbol + vector is guaranteed for relocation. */ + + reloc_objfile_msymbols (objfile, vp->tstart - old_start); +#endif + break; + } } } + if (vp->tstart != old_start) { +#ifndef FASTER_MSYMBOL_RELOCATION (void) iterate_over_msymbols (relocate_minimal_symbol, (PTR) (vp->tstart - old_start), (PTR) NULL, (PTR) NULL); +#endif /* breakpoints need to be relocated as well. */ fixup_breakpoints (0, TEXT_SEGMENT_BASE, vp->tstart - old_start); @@ -416,6 +476,7 @@ struct stat *vip; symtab_relocated = 1; } + vmap_symtab_1(s, vp, old_start) register struct symtab *s; register struct vmap *vp; @@ -515,19 +576,26 @@ CORE_ADDR old_start; add_vmap(ldi) register struct ld_info *ldi; { bfd *bfd, *last; - register char *mem; + register char *mem, *objname; + + /* This ldi structure was allocated using alloca() in + aixcoff_relocate_symtab(). Now we need to have persistent object + and member names, so we should save them. */ mem = ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1; - bfd = bfd_fdopenr(ldi->ldinfo_filename, NULL, ldi->ldinfo_fd); + mem = savestring (mem, strlen (mem)); + objname = savestring (ldi->ldinfo_filename, strlen (ldi->ldinfo_filename)); + + bfd = bfd_fdopenr(objname, NULL, ldi->ldinfo_fd); if (!bfd) - error("Could not open `%s' as an executable file: %s" - , ldi->ldinfo_filename, bfd_errmsg(bfd_error)); + error("Could not open `%s' as an executable file: %s", + objname, bfd_errmsg(bfd_error)); /* make sure we have an object file */ if (bfd_check_format(bfd, bfd_object)) - map_vmap (bfd, 0); + map_vmap (bfd, 0); else if (bfd_check_format(bfd, bfd_archive)) { last = 0; @@ -539,11 +607,10 @@ register struct ld_info *ldi; { break; if (!last) { - bfd_close(bfd); -/* FIXME -- should be error */ - warning("\"%s\": member \"%s\" missing.", - bfd->filename, mem); - return; + bfd_close(bfd); + /* FIXME -- should be error */ + warning("\"%s\": member \"%s\" missing.", bfd->filename, mem); + return; } if (!bfd_check_format(last, bfd_object)) { @@ -558,18 +625,20 @@ register struct ld_info *ldi; { bfd_close(bfd); /* FIXME -- should be error */ warning("\"%s\": not in executable format: %s." - , ldi->ldinfo_filename, bfd_errmsg(bfd_error)); + , objname, bfd_errmsg(bfd_error)); return; } } -/* As well as symbol tables, exec_sections need relocation. Otherwise after - the inferior process terminates, symbol table is relocated but there is - no inferior process. Thus, we have to use `exec' bfd, rather than the inferior - process's memory space, when lookipng at symbols. - `exec_sections' need to be relocated only once though, as long as the exec - file was not changed. +/* As well as symbol tables, exec_sections need relocation. After + the inferior process' termination, there will be a relocated symbol + table exist with no corresponding inferior process. At that time, we + need to use `exec' bfd, rather than the inferior process's memory space + to look up symbols. + + `exec_sections' need to be relocated only once, as long as the exec + file remains unchanged. */ vmap_exec () { @@ -579,17 +648,19 @@ vmap_exec () execbfd = exec_bfd; - if (!vmap || !exec_sections) { - printf ("WARNING: vmap not found in vmap_exec()!\n"); - return; - } /* First exec section is `.text', second is `.data'. If this is changed, - then this routine will choke. Better you should check section names, - FIXMEmgo. */ - exec_sections [0].addr += vmap->tstart; - exec_sections [0].endaddr += vmap->tstart; - exec_sections [1].addr += vmap->dstart; - exec_sections [1].endaddr += vmap->dstart; + then this routine will choke. */ + + if (!vmap || !exec_ops.to_sections || + strcmp (exec_ops.to_sections[0].sec_ptr->name, ".text") || + strcmp (exec_ops.to_sections[1].sec_ptr->name, ".data")) + + fatal ("aix: Improper exec_ops sections."); + + exec_ops.to_sections [0].addr += vmap->tstart; + exec_ops.to_sections [0].endaddr += vmap->tstart; + exec_ops.to_sections [1].addr += vmap->dstart; + exec_ops.to_sections [1].endaddr += vmap->dstart; } @@ -710,10 +781,9 @@ retry: vmap_inferior() { if (inferior_pid == 0) - return 0; /* normal processing */ + return 0; /* normal processing */ exec_files_info(); - return 1; } @@ -791,7 +861,6 @@ print_section_info (t, abfd) struct target_ops *t; bfd *abfd; { -#if 1 struct section_table *p; printf_filtered ("\t`%s', ", bfd_get_filename(abfd)); @@ -810,32 +879,32 @@ print_section_info (t, abfd) } printf_filtered ("\n"); } -#else - register struct vmap *vp = vmap; - - if (!vp) - return; - - printf("\tMapping info for file `%s'.\n", vp->name); - printf("\t %8.8s %8.8s %8.8s %s\n" - , "start", "end", "section", "file(member)"); - - for (; vp; vp = vp->nxt) - printf("\t0x%8.8x 0x%8.8x %s%s%s%s\n" - , vp->tstart - , vp->tend - , vp->name - , *vp->member ? "(" : "" - , vp->member - , *vp->member ? ")" : ""); -#endif } + static void exec_files_info (t) struct target_ops *t; { + register struct vmap *vp = vmap; + print_section_info (t, exec_bfd); + + if (!vp) + return; + + printf("\n\tMapping info for file `%s'.\n", vp->name); + printf("\t %8.8s %8.8s %8.8s %s\n", + "start", "end", "section", "file(member)"); + + for (; vp; vp = vp->nxt) + printf("\t0x%8.8x 0x%8.8x %s%s%s%s\n", + vp->tstart, + vp->tend, + vp->name, + vp->member ? "(" : "", + vp->member, + vp->member ? ")" : ""); } #ifdef DAMON @@ -909,13 +978,14 @@ set_section_command (args, from_tty) /* Parse out new virtual address */ secaddr = parse_and_eval_address (args); - for (p = exec_sections; p < exec_sections_end; p++) { + for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) { if (!strncmp (secname, bfd_section_name (exec_bfd, p->sec_ptr), seclen) && bfd_section_name (exec_bfd, p->sec_ptr)[seclen] == '\0') { offset = secaddr - p->addr; p->addr += offset; p->endaddr += offset; - exec_files_info(); + if (from_tty) + exec_files_info(&exec_ops); return; } } diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c index 738af31..90d5f30 100644 --- a/gdb/xcoffread.c +++ b/gdb/xcoffread.c @@ -1285,7 +1285,11 @@ function_entry_point: } /* shared library function trampoline code entry point. */ else if (CSECT_SCLAS (main_aux) == XMC_GL) { - RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_text, + + /* record trampoline code entries as mst_unknown symbol. When we + lookup mst symbols, we will choose mst_text over mst_unknown. */ + + RECORD_MINIMAL_SYMBOL (cs->c_name, cs->c_value, mst_unknown, symname_alloced); continue; } @@ -1622,11 +1626,12 @@ process_xcoff_symbol (cs, objfile) char *tmp_pp = pp; read_type_number (&tmp_pp, typenums); - tmp_type = dbx_alloc_type (typenums); + tmp_type = dbx_alloc_type (typenums, objfile); if (tmp_type && !TYPE_NAME (tmp_type) && !nameless) TYPE_NAME (tmp_type) = SYMBOL_NAME (sym) = - obsavestring (name, qq-name); + obsavestring (name, qq-name, + &objfile->symbol_obstack); } ttype = SYMBOL_TYPE (sym) = read_type (&pp, objfile); @@ -2264,3 +2269,176 @@ char **pp; fatal ("internals eror: builtin_type called!"); } #endif /* IBM6000 */ + + +#define DEBUG 1 + +#ifdef DEBUG +void +dump_strtbl () +{ + int ii; + printf ("===STRING TABLE DUMP...\n\n"); + for ( ii=0; ii < strtbl_len; ++ii ) + printf ("%c", isprint (*(strtbl+ii)) ? *(strtbl+ii) : ' '); + printf ("\n"); +} + +void +dump_linetable (ltb) + struct linetable *ltb; +{ + int ii; + for (ii=0; ii < ltb->nitems; ++ii) + printf ("line: %d, addr: 0x%x\n", ltb->item[ii].line, ltb->item[ii].pc); +} + +void +dump_type (typeP) + struct type *typeP; +{ + printf ("0x%x: name: %s\n", typeP, typeP->name ? typeP->name : "(nil)"); +} + +char *dump_namespace (); +char *dump_addrclass (); + +void +dump_symbol (pp) + struct symbol *pp; +{ + printf (" sym: %s\t%s,\t%s\ttype: 0x%x, val: 0x%x end: 0x%x\n", + pp->name, dump_namespace (pp->namespace), + dump_addrclass (pp->class), pp->type, + SYMBOL_CLASS(pp) == LOC_BLOCK ? BLOCK_START(SYMBOL_BLOCK_VALUE(pp)) + : pp->value.value, + SYMBOL_CLASS(pp) == LOC_BLOCK ? BLOCK_END(SYMBOL_BLOCK_VALUE(pp)) : 0); +} + + +char * +dump_namespace (ns) +int ns; +{ + static char *ns_name [] = { + "UNDEF_NS", "VAR_NS", "STRUCT_NS", "LABEL_NS"}; + + switch (ns) { + case UNDEF_NAMESPACE: + case VAR_NAMESPACE: + case STRUCT_NAMESPACE: + case LABEL_NAMESPACE: + return ns_name[ns]; + } + + return "***ERROR***"; +} + + +char * +dump_addrclass (ac) +int ac; /* address class */ +{ + static char *ac_name [] = { + "LOC_UNDEF", + "LOC_CONST", + "LOC_STATIC", + "LOC_REGISTER", + "LOC_ARG", + "LOC_REF_ARG", + "LOC_REGPARM", + "LOC_LOCAL", + "LOC_TYPEDEF", + "LOC_LABEL", + "LOC_BLOCK", + "LOC_CONST_BYTES", + "LOC_LOCAL_ARG", + }; + switch (ac) { + case LOC_UNDEF: + case LOC_CONST: + case LOC_STATIC: + case LOC_REGISTER: + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_LOCAL: + case LOC_TYPEDEF: + case LOC_LABEL: + case LOC_BLOCK: + case LOC_CONST_BYTES: + case LOC_LOCAL_ARG: + return ac_name [ac]; + } + return "***ERROR***"; +} + +void +dump_block (pp) + struct block *pp; +{ + int ii; + printf ("BLOCK..: start: 0x%x, end: 0x%x\n", pp->startaddr, pp->endaddr); + for (ii=0; ii < pp->nsyms; ++ii) + dump_symbol (pp->sym[ii]); +} + +void +dump_blockvector (pp) + struct blockvector *pp; +{ + int ii; + for (ii=0; ii < pp->nblocks; ++ii) + dump_block (pp->block [ii]); +} + + +void +dump_last_symtab (pp) + struct symtab *pp; +{ + for ( ; pp; pp = pp->next) { + if ( pp->next == 0 ) { + printf ("SYMTAB NAME: %s\n", pp->filename); + dump_blockvector (pp->blockvector); + } + } +} + +void +dump_symtabs (pp) + struct symtab *pp; +{ + for ( ; pp; pp = pp->next) { + printf ("SYMTAB NAME: %s\n", pp->filename ? pp->filename : "(nil)"); +/* if (pp->linetable) + dump_linetable (pp->linetable); */ + dump_blockvector (pp->blockvector); + } +} + +void +dump_symtab_lines (pp) + struct symtab *pp; +{ + for ( ; pp; pp = pp->next) { + printf ("SYMTAB NAME: %s\n", pp->filename ? pp->filename : "(nil)"); + if (pp->linetable) + dump_linetable (pp->linetable); + /* dump_blockvector (pp->blockvector); */ + } +} + +void +dump_msymbols (of) +struct objfile *of; +{ + int ii; + for (ii=0; ii < of->minimal_symbol_count; ++ii) + printf ("name: %s, addr: 0x%x, info: 0x%x\n", + of->msymbols[ii].name, + of->msymbols[ii].address, + of->msymbols[ii].info ); +} + +#endif /* DEBUG */ |