diff options
author | John Gilmore <gnu@cygnus> | 1991-11-12 15:50:47 +0000 |
---|---|---|
committer | John Gilmore <gnu@cygnus> | 1991-11-12 15:50:47 +0000 |
commit | 41abdfbd2de07837ba8088092765154eaa66351d (patch) | |
tree | bb912925e95a78628143f4d2e98b0c32e372f3ac /gdb/xcoffexec.c | |
parent | 37b637f3b7327782b3217f1655fea4258cfb1701 (diff) | |
download | gdb-41abdfbd2de07837ba8088092765154eaa66351d.zip gdb-41abdfbd2de07837ba8088092765154eaa66351d.tar.gz gdb-41abdfbd2de07837ba8088092765154eaa66351d.tar.bz2 |
* rs6000-pinsn.c, rs6000-tdep.c, rs6000-xdep.c, tm-rs6000.h,
xm-rs6000.h: New files.
* xcoffexec.c: New file for handling AIX shared libraries.
Diffstat (limited to 'gdb/xcoffexec.c')
-rw-r--r-- | gdb/xcoffexec.c | 932 |
1 files changed, 932 insertions, 0 deletions
diff --git a/gdb/xcoffexec.c b/gdb/xcoffexec.c new file mode 100644 index 0000000..f1bd3d8 --- /dev/null +++ b/gdb/xcoffexec.c @@ -0,0 +1,932 @@ +/* Execute AIXcoff files, for GDB. + Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc. + Derived from exec.c. Modified by IBM Corporation. + Donated by IBM Corporation and Cygnus Support. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* xcoff-exec - deal with executing XCOFF files. */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/param.h> +#include <fcntl.h> +#include <string.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/ldr.h> + +#include "defs.h" +#include "param.h" +#include "frame.h" +#include "inferior.h" +#include "target.h" +#include "gdbcmd.h" +#include "gdbcore.h" +#include "symfile.h" + +#include "libbfd.h" /* BFD internals (sigh!) FIXME */ + +struct section_table *exec_sections, *exec_sections_end; + +#define eq(s0, s1) !strcmp(s0, s1) + +/* Whether to open exec and core files read-only or read-write. */ + +int write_files = 0; + +bfd *exec_bfd; /* needed by core.c */ + +extern char *getenv(); +extern void child_create_inferior (), child_attach (); +extern void add_syms_addr_command (); +extern void symbol_file_command (); +static void exec_files_info(); + +/* + * the vmap struct is used to describe the virtual address space of + * the target we are manipulating. The first entry is always the "exec" + * file. Subsequent entries correspond to other objects that are + * mapped into the address space of a process created from the "exec" file. + * These are either in response to exec()ing the file, in which case all + * shared libraries are loaded, or a "load" system call, followed by the + * user's issuance of a "load" command. + */ +struct vmap { + struct vmap *nxt; /* ^ to next in chain */ + bfd *bfd; /* BFD for mappable object library */ + char *name; /* ^ to object file name */ + char *member; /* ^ to member name */ + CORE_ADDR tstart; /* virtual addr where member is mapped */ + CORE_ADDR tend; /* virtual upper bound of member */ + CORE_ADDR tadj; /* heuristically derived adjustment */ + CORE_ADDR dstart; /* virtual address of data start */ + CORE_ADDR dend; /* vitrual address of data end */ +}; + + +struct vmap_and_bfd { + bfd *pbfd; + struct vmap *pvmap; +}; + +static struct vmap *vmap; /* current vmap */ + +extern struct target_ops exec_ops; + + +/* exec_close - done with exec file, clean up all resources. */ + +void +exec_close(quitting) { + register struct vmap *vp, *nxt; + + for (nxt = vmap; vp = nxt; ) { + nxt = vp->nxt; + bfd_close(vp->bfd); + free_named_symtabs(vp->name, vp->member); /* XXX */ + free(vp); + } + + vmap = 0; + exec_bfd = 0; +} + +/* + * exec_file_command - handle the "exec" command, &c. + */ +void +exec_file_command(filename, from_tty) +char *filename; +{ + bfd *bfd; + + target_preopen(from_tty); + unpush_target(&exec_ops); + + /* Now open and digest the file the user requested, if any. */ + + if (filename) { + char *scratch_pathname; + int scratch_chan; + + filename = tilde_expand(filename); + make_cleanup(free, filename); + + scratch_chan = openp(getenv("PATH"), 1, filename, O_RDONLY, 0 + , &scratch_pathname); + if (scratch_chan < 0) + perror_with_name(filename); + + bfd = bfd_fdopenr(scratch_pathname, NULL, scratch_chan); + if (!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)); + + + /* setup initial vmap */ + + map_vmap (bfd, 0); + if (!vmap) + error("Can't find the file sections in `%s': %s" + , bfd->filename, bfd_errmsg(bfd_error)); + + exec_bfd = bfd; + + if (build_section_table (exec_bfd, &exec_sections, &exec_sections_end)) + error ("Can't find the file sections in `%s': %s", + exec_bfd->filename, bfd_errmsg (bfd_error)); + + /* make sure core, if present, matches */ + validate_files(); + + push_target(&exec_ops); + + /* Tell display code(if any) about the changed file name. */ + + if (exec_file_display_hook) + (*exec_file_display_hook)(filename); + } + else { + exec_close(0); /* just in case */ + if (from_tty) + printf("No exec file now.\n"); + } +} + +/* Set both the exec file and the symbol file, in one command. What a + * novelty. Why did GDB go through four major releases before this + * command was added? + */ +void +file_command(arg, from_tty) +char *arg; { + + exec_file_command(arg, from_tty); + symbol_file_command(arg, from_tty); +} + +/* Locate all mappable sections of a BFD file. + table_pp_char is a char * to get it through bfd_map_over_sections; + we cast it back to its proper type. */ + +void +add_to_section_table (abfd, asect, table_pp_char) + bfd *abfd; + sec_ptr asect; + char *table_pp_char; +{ + struct section_table **table_pp = (struct section_table **)table_pp_char; + flagword aflag; + + aflag = bfd_get_section_flags (abfd, asect); + /* FIXME, we need to handle BSS segment here...it alloc's but doesn't load */ + if (!(aflag & SEC_LOAD)) + return; + (*table_pp)->sec_ptr = asect; + (*table_pp)->addr = bfd_section_vma (abfd, asect); + (*table_pp)->endaddr = (*table_pp)->addr + bfd_section_size (abfd, asect); + (*table_pp)++; +} + +int +build_section_table (some_bfd, start, end) + bfd *some_bfd; + struct section_table **start, **end; +{ + unsigned count; + + count = bfd_count_sections (some_bfd); + if (count == 0) + abort(); /* return 1? */ + if (*start) + free (*start); + *start = (struct section_table *) xmalloc (count * sizeof (**start)); + *end = *start; + bfd_map_over_sections (some_bfd, add_to_section_table, (char *)end); + if (*end > *start + count) + abort(); + /* We could realloc the table, but it probably loses for most files. */ + return 0; +} + +/* + * lookup_symtab_bfd - find if we currently have any symbol tables from bfd + */ +struct objfile * +lookup_objfile_bfd(bfd *bfd) { + register struct objfile *s; + + for (s = object_files; s; s = s->next) + if (s->obfd == bfd) + return s; + return 0; +} + + +void +sex_to_vmap(bfd *bf, sec_ptr sex, struct vmap_and_bfd *vmap_bfd) +{ + register struct vmap *vp, **vpp; + register struct symtab *syms; + bfd *arch = vmap_bfd->pbfd; + vp = vmap_bfd->pvmap; + + if ((bfd_get_section_flags(bf, sex) & SEC_LOAD) == 0) + return; + + if (!strcmp(bfd_section_name(bf, sex), ".text")) { + 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; + } + + else if (!strcmp(bfd_section_name(bf, sex), ".data")) { + vp->dstart = 0; + vp->dend = vp->dstart + bfd_section_size(bf, sex); + } + + else if (!strcmp(bfd_section_name(bf, sex), ".bss")) /* FIXMEmgo */ + printf ("bss section in exec! Don't know what the heck to do!\n"); +} + +/* Make a vmap for the BFD "bf", which might be a member of the archive + BFD "arch". If we have not yet read in symbols for this file, do so. */ + +map_vmap (bfd *bf, bfd *arch) +{ + struct vmap_and_bfd vmap_bfd; + struct vmap *vp, **vpp; + struct objfile *obj; + char *name; + + vp = (void*) xmalloc (sizeof (*vp)); + vp->nxt = 0; + vp->bfd = bf; + vp->name = bfd_get_filename(arch ? arch : bf); + vp->member = arch ? bfd_get_filename(bf) : ""; + + vmap_bfd.pbfd = arch; + vmap_bfd.pvmap = vp; + bfd_map_over_sections (bf, sex_to_vmap, &vmap_bfd); + + obj = lookup_objfile_bfd (bf); + if (exec_bfd && !obj) { + name = savestring (bfd_get_filename (bf), strlen (bfd_get_filename (bf))); + obj = allocate_objfile (bf, name); + syms_from_objfile (obj, 0, 0); + } + + /* find the end of the list, and append. */ + for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt) + ; + *vpp = vp; +} + + +/* true, if symbol table and misc_function_vector is relocated. */ + +int symtab_relocated = 0; + + +/* vmap_symtab - handle symbol translation on vmapping */ + +vmap_symtab(vp, old_start, vip) +register struct vmap *vp; +CORE_ADDR old_start; +struct stat *vip; +{ + register struct symtab *s; + + /* + * for each symbol table generated from the vp->bfd + */ + for (s = symtab_list; s; s = s->next) { + + /* skip over if this is not relocatable and doesn't have a line table */ + if (s->nonreloc && !LINETABLE (s)) + continue; + + /* matching the symbol table's BFD and the *vp's BFD is hairy. + exec_file creates a seperate BFD for possibly the + same file as symbol_file.FIXME ALL THIS MUST BE RECTIFIED. */ + + if (s->objfile->obfd == vp->bfd) { + /* if they match, we luck out. */ + ; + } else if (vp->member[0]) { + /* no match, and member present, not this one. */ + continue; + } else { + struct stat si; + FILE *io; + + /* + * no match, and no member. need to be sure. + */ + io = bfd_cache_lookup(s->objfile->obfd); + if (!io) + fatal("cannot find BFD's iostream for sym"); + /* + * see if we are referring to the same file + */ + if (fstat(fileno(io), &si) < 0) + fatal("cannot fstat BFD for sym"); + + if (si.st_dev != vip->st_dev + || si.st_ino != vip->st_ino) + continue; + } + + if (vp->tstart != old_start) + vmap_symtab_1(s, vp, old_start); + } + + if (vp->tstart != old_start) + fixup_misc_vector (vp->tstart - old_start); + + symtab_relocated = 1; +} + + +fixup_misc_vector (int disp) +{ + int ii; + for (ii=0; ii < misc_function_count; ++ii) + if (misc_function_vector[ii].address < 0x10000000) + misc_function_vector[ii].address += disp; +} + + +vmap_symtab_1(s, vp, old_start) +register struct symtab *s; +register struct vmap *vp; +CORE_ADDR old_start; +{ + register int i, j; + int len, blen; + register struct linetable *l; + struct blockvector *bv; + register struct block *b; + int depth; + register ulong reloc, dreloc; + + if ((reloc = vp->tstart - old_start) == 0) + return; + + dreloc = vp->dstart; /* data relocation */ + + /* + * The line table must be relocated. This is only present for + * b.text sections, so only vp->text type maps need be considered. + */ + l = LINETABLE (s); + len = l->nitems; + for (i = 0; i < len; i++) + l->item[i].pc += reloc; + + /* if this symbol table is not relocatable, only line table should + be relocated and the rest ignored. */ + if (s->nonreloc) + return; + + bv = BLOCKVECTOR(s); + len = BLOCKVECTOR_NBLOCKS(bv); + + for (i = 0; i < len; i++) { + b = BLOCKVECTOR_BLOCK(bv, i); + + BLOCK_START(b) += reloc; + BLOCK_END(b) += reloc; + + blen = BLOCK_NSYMS(b); + for (j = 0; j < blen; j++) { + register struct symbol *sym; + + sym = BLOCK_SYM(b, j); + switch (SYMBOL_NAMESPACE(sym)) { + case STRUCT_NAMESPACE: + case UNDEF_NAMESPACE: + continue; + + case LABEL_NAMESPACE: + case VAR_NAMESPACE: + break; + } + + switch (SYMBOL_CLASS(sym)) { + case LOC_CONST: + case LOC_CONST_BYTES: + case LOC_LOCAL: + case LOC_REGISTER: + case LOC_ARG: + case LOC_LOCAL_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_TYPEDEF: + continue; + +#ifdef FIXME + case LOC_EXTERNAL: +#endif + case LOC_LABEL: + SYMBOL_VALUE_ADDRESS(sym) += reloc; + break; + + case LOC_STATIC: + SYMBOL_VALUE_ADDRESS(sym) += dreloc; + break; + + case LOC_BLOCK: + break; + + default: + fatal("botched symbol class %x" + , SYMBOL_CLASS(sym)); + break; + } + } + } +} + +/* + * add_vmap - add a new vmap entry based on ldinfo() information + */ +add_vmap(ldi) +register struct ld_info *ldi; { + bfd *bfd, *last; + register char *mem; + + mem = ldi->ldinfo_filename + strlen(ldi->ldinfo_filename) + 1; + bfd = bfd_fdopenr(ldi->ldinfo_filename, NULL, ldi->ldinfo_fd); + if (!bfd) + error("Could not open `%s' as an executable file: %s" + , ldi->ldinfo_filename, bfd_errmsg(bfd_error)); + + + /* make sure we have an object file */ + + if (bfd_check_format(bfd, bfd_object)) + map_vmap (bfd, 0); + + else if (bfd_check_format(bfd, bfd_archive)) { + last = 0; + /* + * FIXME??? am I tossing BFDs? bfd? + */ + while (last = bfd_openr_next_archived_file(bfd, last)) + if (eq(mem, last->filename)) + break; + + if (!last) { + bfd_close(bfd); +/* FIXME -- should be error */ + warning("\"%s\": member \"%s\" missing.", + bfd->filename, mem); + return; + } + + if (!bfd_check_format(last, bfd_object)) { + bfd_close(last); /* XXX??? */ + goto obj_err; + } + + map_vmap (last, bfd); + } + else { + obj_err: + bfd_close(bfd); +/* FIXME -- should be error */ + warning("\"%s\": not in executable format: %s." + , ldi->ldinfo_filename, 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. +*/ +vmap_exec () +{ + static bfd *execbfd; + if (execbfd == exec_bfd) + return; + + 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; +} + + +int +text_adjustment (abfd) +bfd *abfd; +{ + static bfd *execbfd; + static int adjustment; + sec_ptr sect; + + if (exec_bfd == execbfd) + return adjustment; + + sect = bfd_get_section_by_name (abfd, ".text"); + if (sect) + adjustment = sect->filepos - sect->vma; + else + adjustment = 0x200; /* just a wild assumption */ + + return adjustment; +} + + +/* + * vmap_ldinfo - update VMAP info with ldinfo() information + * + * Input: + * ldi - ^ to ldinfo() results. + */ +vmap_ldinfo(ldi) +register struct ld_info *ldi; +{ + struct stat ii, vi; + register struct vmap *vp; + register got_one, retried; + CORE_ADDR ostart; + + /* + * for each *ldi, see if we have a corresponding *vp + * if so, update the mapping, and symbol table. + * if not, add an entry and symbol table. + */ + do { + char *name = ldi->ldinfo_filename; + char *memb = name + strlen(name) + 1; + + retried = 0; + + if (fstat(ldi->ldinfo_fd, &ii) < 0) + fatal("cannot fstat(%d) on %s" + , ldi->ldinfo_fd + , name); +retry: + for (got_one = 0, vp = vmap; vp; vp = vp->nxt) { + FILE *io; + + /* The filenames are not always sufficient to match on. */ + if ((name[0] == "/" + && !eq(name, vp->name)) + || (memb[0] && !eq(memb, vp->member))) + continue; + + /* totally opaque! */ + io = bfd_cache_lookup(vp->bfd); + if (!io) + fatal("cannot find BFD's iostream for %s" + , vp->name); + + /* see if we are referring to the same file */ + if (fstat(fileno(io), &vi) < 0) + fatal("cannot fstat BFD for %s", vp->name); + + if (ii.st_dev != vi.st_dev || ii.st_ino != vi.st_ino) + continue; + + if (!retried) + close(ldi->ldinfo_fd); + + ++got_one; + + /* found a corresponding VMAP. remap! */ + ostart = vp->tstart; + + vp->tstart = ldi->ldinfo_textorg; + vp->tend = vp->tstart + ldi->ldinfo_textsize; + vp->dstart = ldi->ldinfo_dataorg; + vp->dend = vp->dstart + ldi->ldinfo_datasize; + + if (vp->tadj) { + vp->tstart += vp->tadj; + vp->tend += vp->tadj; + } + + /* relocate symbol table(s). */ + vmap_symtab(vp, ostart, &vi); + + /* there may be more, so we don't break out of the loop. */ + } + + /* + * if there was no matching *vp, we must perforce create + * the sucker(s) + */ + if (!got_one && !retried) { + add_vmap(ldi); + ++retried; + goto retry; + } + } while (ldi->ldinfo_next + && (ldi = (void *) (ldi->ldinfo_next + (char *) ldi))); + + breakpoint_re_set(); +} + +/* + * vmap_inferior - print VMAP info for inferior + */ +vmap_inferior() { + + if (inferior_pid == 0) + return 0; /* normal processing */ + + exec_files_info(); + + return 1; +} + +/* Read or write the exec file. + + Args are address within exec file, address within gdb address-space, + length, and a flag indicating whether to read or write. + + Result is a length: + + 0: We cannot handle this address and length. + > 0: We have handled N bytes starting at this address. + (If N == length, we did it all.) We might be able + to handle more bytes beyond this length, but no + promises. + < 0: We cannot handle this address, but if somebody + else handles (-N) bytes, we can start from there. + + The same routine is used to handle both core and exec files; + we just tail-call it with more arguments to select between them. */ + +int +xfer_memory (memaddr, myaddr, len, write, abfd, sections, sections_end) + CORE_ADDR memaddr; + char *myaddr; + int len; + int write; + bfd *abfd; + struct section_table *sections, *sections_end; +{ + boolean res; + struct section_table *p; + CORE_ADDR nextsectaddr, memend; + boolean (*xfer_fn) (); + + if (len <= 0) + abort(); + + memend = memaddr + len; + xfer_fn = write? bfd_set_section_contents: bfd_get_section_contents; + nextsectaddr = memend; + + for (p = sections; p < sections_end; p++) + { + if (p->addr <= memaddr) + if (p->endaddr >= memend) + { + /* Entire transfer is within this section. */ + res = xfer_fn (abfd, p->sec_ptr, myaddr, memaddr - p->addr, len); + return (res != false)? len: 0; + } + else if (p->endaddr <= memaddr) + { + /* This section ends before the transfer starts. */ + continue; + } + else + { + /* This section overlaps the transfer. Just do half. */ + len = p->endaddr - memaddr; + res = xfer_fn (abfd, p->sec_ptr, myaddr, memaddr - p->addr, len); + return (res != false)? len: 0; + } + else if (p->addr < nextsectaddr) + nextsectaddr = p->addr; + } + + if (nextsectaddr >= memend) + return 0; /* We can't help */ + else + return - (nextsectaddr - memaddr); /* Next boundary where we can help */ +} + +/* The function called by target_xfer_memory via our target_ops */ + +int +exec_xfer_memory (memaddr, myaddr, len, write) + CORE_ADDR memaddr; + char *myaddr; + int len; + int write; +{ + return xfer_memory (memaddr, myaddr, len, write, + exec_bfd, exec_sections, exec_sections_end); +} + +/* + * exec_files_info - "info files" command processor + */ +static void +exec_files_info() { + 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 ? ")" : ""); +} + +#ifdef DAMON + Damon's implementation of set_section_command! It is based on the sex member + (which is a section pointer from vmap) of vmap. + We will not have multiple vmap entries (one for each section), rather transmit + text and data base offsets and fix them at the same time. Elimination of sex + entry in vmap make this function obsolute, use the one from exec.c. + Need further testing!! FIXMEmgo. + +static void +set_section_command(args, from_tty) +char *args; +{ + register struct vmap *vp = vmap; + char *secname; + unsigned seclen; + unsigned long secaddr; + char secprint[100]; + long offset; + + if (args == 0) + error("Must specify section name and its virtual address"); + + /* Parse out section name */ + for (secname = args; !isspace(*args); args++) + ; + seclen = args - secname; + + /* Parse out new virtual address */ + secaddr = parse_and_eval_address(args); + + for (vp = vmap; vp; vp = vp->nxt) { + if (!strncmp(secname + , bfd_section_name(vp->bfd, vp->sex), seclen) + && bfd_section_name(vp->bfd, vp->sex)[seclen] == '\0') { + offset = secaddr - vp->tstart; + vp->tstart += offset; + vp->tend += offset; + exec_files_info(); + return; + } + } + + if (seclen >= sizeof(secprint)) + seclen = sizeof(secprint) - 1; + strncpy(secprint, secname, seclen); + secprint[seclen] = '\0'; + error("Section %s not found", secprint); +} +#else +static void +set_section_command (args, from_tty) + char *args; + int from_tty; +{ + struct section_table *p; + char *secname; + unsigned seclen; + unsigned long secaddr; + char secprint[100]; + long offset; + + if (args == 0) + error ("Must specify section name and its virtual address"); + + /* Parse out section name */ + for (secname = args; !isspace(*args); args++) ; + seclen = args - secname; + + /* Parse out new virtual address */ + secaddr = parse_and_eval_address (args); + + for (p = exec_sections; p < exec_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(); + return; + } + } + if (seclen >= sizeof (secprint)) + seclen = sizeof (secprint) - 1; + strncpy (secprint, secname, seclen); + secprint[seclen] = '\0'; + error ("Section %s not found", secprint); +} + +#endif /* !DAMON */ + +struct target_ops exec_ops = { + "exec", "Local exec file", + "Use an executable file as a target.\n\ +Specify the filename of the executable file.", + exec_file_command, exec_close, /* open, close */ + child_attach, 0, 0, 0, /* attach, detach, resume, wait, */ + 0, 0, /* fetch_registers, store_registers, */ + 0, 0, 0, /* prepare_to_store, conv_to, conv_from, */ + exec_xfer_memory, exec_files_info, + 0, 0, /* insert_breakpoint, remove_breakpoint, */ + 0, 0, 0, 0, 0, /* terminal stuff */ + 0, 0, /* kill, load */ + 0, 0, /* call fn, lookup sym */ + child_create_inferior, + 0, /* mourn_inferior */ + file_stratum, 0, /* next */ + 0, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */ + 0, 0, /* section pointers */ + OPS_MAGIC, /* Always the last thing */ +}; + + +void +_initialize_exec() +{ + + add_com("file", class_files, file_command, + "Use FILE as program to be debugged.\n\ +It is read for its symbols, for getting the contents of pure memory,\n\ +and it is the program executed when you use the `run' command.\n\ +If FILE cannot be found as specified, your execution directory path\n\ +($PATH) is searched for a command of that name.\n\ +No arg means to have no executable file and no symbols."); + + add_com("exec-file", class_files, exec_file_command, + "Use FILE as program for getting contents of pure memory.\n\ +If FILE cannot be found as specified, your execution directory path\n\ +is searched for a command of that name.\n\ +No arg means have no executable file."); + + add_com("section", class_files, set_section_command, + "Change the base address of section SECTION of the exec file to ADDR.\n\ +This can be used if the exec file does not contain section addresses,\n\ +(such as in the a.out format), or when the addresses specified in the\n\ +file itself are wrong. Each section must be changed separately. The\n\ +``info files'' command lists all the sections and their addresses."); + + add_target(&exec_ops); +} |