diff --git a/gdb/corelow.c b/gdb/corelow.c index 35c998c..c9b22e5 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -33,6 +33,8 @@ #include "symtab.h" #include "command.h" #include "bfd.h" +#include "elf-bfd.h" +#include "elf/internal.h" #include "target.h" #include "gdbcore.h" #include "gdbthread.h" @@ -45,6 +47,7 @@ #include "exceptions.h" #include "solib.h" #include "filenames.h" +#include "objfiles.h" #ifndef O_LARGEFILE @@ -692,6 +695,161 @@ core_pid_to_str (ptid_t ptid) return buf; } +/* Helper function for 'core_print_proc_map'. It is used to iterate + over the corefile's sections and print proper information about + memory-mappings. + + BFD is the bfd used to get the sections. + SECT is the current section being "visited". + OBJ is not used. */ + +static void +print_proc_map_iter (bfd *bfd, asection *sect, void *obj) +{ + /* We're interested in matching sections' names beginning with + "load", because they are the sections containing information + about the process' memory regions. */ + static const char *proc_map_match = "load"; + int proc_map_match_size = strlen (proc_map_match); + /* A little flag to indicate whether we have found something. */ + int found = 0; + /* The section's size. */ + bfd_size_type secsize; + /* We have to know the bitness of this architecture. */ + struct gdbarch *gdbarch = gdbarch_from_bfd (bfd); + int bitness = gdbarch_addr_bit (gdbarch); + /* We'll use these later. They are basically used for iterating + over every objfile in the system so that we can find needed + information about the memory region being examinated. */ + struct obj_section *s = NULL; + struct objfile *objfile = NULL; + /* Fields to be printed for the proc map. */ + unsigned long start = 0, end = 0; + unsigned int size = 0; + char *filename = NULL; + + if (strncmp (proc_map_match, sect->name, proc_map_match_size) != 0) + /* This section is not useful. */ + return; + + /* Unfortunately, some sections in the corefile don't have any + content inside. This is bad because we need to print, among + other things, its final address in the memory (which is + impossible to know if we don't have a size). That's why we + first need to check if the section's got anything inside it. */ + secsize = bfd_section_size (bfd, sect); + + if (secsize == 0) + { + /* Ok, the section if empty. In this case, we must look inside + ELF's Program Header, because (at least) there we have + information about the section's size. That's what we're doing + here. */ + Elf_Internal_Phdr *p = elf_tdata (bfd)->phdr; + if (p != NULL) + { + int i; + unsigned int n = elf_elfheader (bfd)->e_phnum; + for (i = 0; i < n; i++, p++) + /* For each entry in the Program Header, we have to + check if the section's initial address is equal to + the entry's virtual address. If it is, then we + have just found the section's entry in the Program + Header, and can use the entry's information to + complete missing data from the section. */ + if (sect->vma == p->p_vaddr) + { + found = 1; + break; + } + if (found) + secsize = p->p_memsz; + } + } + + size = secsize; + start = sect->vma; + end = (unsigned long) (sect->vma + size); + + /* Now begins a new part of the work. We still don't have complete + information about the memory region. For example, we still need + to know the filename which is represented by the region. Such + info can be gathered from the objfile's data structure, and for + that we must iterate over all the objsections and check if the + objsection's initial address is inside the section we have at hand. + If it is, then we can use this specific objsection to obtain the + missing data. */ + found = 0; + ALL_OBJSECTIONS (objfile, s) + if (obj_section_addr (s) >= start + && obj_section_addr (s) <= end) + { + found = 1; + goto out; + } + +out: + if (found) + filename = s->objfile->name; + + if (bitness == 32) + { + printf_filtered ("\t%#10lx %#10lx %#10x %7s\n", + start, + end, + (int) size, + (filename != NULL) ? filename : ""); + } + else + { + printf_filtered (" %#18lx %#18lx %#10x %7s\n", + start, + end, + (int) size, + (filename != NULL) ? filename : ""); + } +} + +/* Implements the "info proc map" command when the user has provided + a corefile. In this case, the PID argument will not be used. */ + +static void +core_print_proc_map (long long pid) +{ + struct gdbarch *gdbarch; + const char *exe; + int bitness; + + gdb_assert (core_bfd != NULL); + + gdbarch = gdbarch_from_bfd (core_bfd); + bitness = gdbarch_addr_bit (gdbarch); + + /* Getting the executable name. */ + exe = bfd_core_file_failing_command (core_bfd); + + printf_filtered (_("exe = '%s'\n"), exe); + printf_filtered (_("Mapped address spaces:\n\n")); + if (bitness == 32) + { + printf_filtered ("\t%10s %10s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", "objfile"); + } + else + { + printf_filtered (" %18s %18s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", "objfile"); + } + + bfd_map_over_sections (core_bfd, + print_proc_map_iter, + NULL); +} + /* Fill in core_ops with its defined operations and properties. */ static void @@ -714,6 +872,7 @@ init_core_ops (void) core_ops.to_create_inferior = find_default_create_inferior; core_ops.to_thread_alive = core_file_thread_alive; core_ops.to_read_description = core_read_description; + core_ops.to_print_proc_map = core_print_proc_map; core_ops.to_pid_to_str = core_pid_to_str; core_ops.to_stratum = core_stratum; core_ops.to_has_memory = 1; diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index a2cb39d..2e3fcbc 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -3586,6 +3586,75 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) return note_data; } +/* Implement the "info proc map" command when the process + being debugged is running (i.e., a corefile is not being + used. */ +static void +linux_nat_print_proc_map (long long pid) +{ + char fname1[MAXPATHLEN]; + FILE *procfile; + + sprintf (fname1, "/proc/%lld/maps", pid); + if ((procfile = fopen (fname1, "r")) != NULL) + { + long long addr, endaddr, size, offset, inode; + char permissions[8], device[8], filename[MAXPATHLEN]; + struct cleanup *cleanup; + + cleanup = make_cleanup_fclose (procfile); + printf_filtered (_("Mapped address spaces:\n\n")); + if (gdbarch_addr_bit (current_gdbarch) == 32) + { + printf_filtered ("\t%10s %10s %10s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", " Offset", "objfile"); + } + else + { + printf_filtered (" %18s %18s %10s %10s %7s\n", + "Start Addr", + " End Addr", + " Size", " Offset", "objfile"); + } + + while (read_mapping (procfile, &addr, &endaddr, &permissions[0], + &offset, &device[0], &inode, &filename[0])) + { + size = endaddr - addr; + + /* FIXME: carlton/2003-08-27: Maybe the printf_filtered + calls here (and possibly above) should be abstracted + out into their own functions? Andrew suggests using + a generic local_address_string instead to print out + the addresses; that makes sense to me, too. */ + + if (gdbarch_addr_bit (current_gdbarch) == 32) + { + printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n", + (unsigned long) addr, /* FIXME: pr_addr */ + (unsigned long) endaddr, + (int) size, + (unsigned int) offset, + filename[0] ? filename : ""); + } + else + { + printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n", + (unsigned long) addr, /* FIXME: pr_addr */ + (unsigned long) endaddr, + (int) size, + (unsigned int) offset, + filename[0] ? filename : ""); + } + } + do_cleanups (cleanup); + } + else + warning (_("unable to open /proc file '%s'"), fname1); +} + /* Implement the "info proc" command. */ static void @@ -3621,6 +3690,12 @@ linux_nat_info_proc_cmd (char *args, int from_tty) else if (strncmp (argv[0], "mappings", strlen (argv[0])) == 0) { mappings_f = 1; + if (current_target.to_stratum == core_stratum) + { + cmdline_f = 0; + cwd_f = 0; + exe_f = 0; + } } else if (strcmp (argv[0], "status") == 0) { @@ -3652,14 +3727,17 @@ linux_nat_info_proc_cmd (char *args, int from_tty) } argv++; } - if (pid == 0) - error (_("No current process: you must name one.")); + if (current_target.to_stratum != core_stratum) + { + if (pid == 0) + error (_("No current process: you must name one.")); - sprintf (fname1, "/proc/%lld", pid); - if (stat (fname1, &dummy) != 0) - error (_("No /proc directory: '%s'"), fname1); + sprintf (fname1, "/proc/%lld", pid); + if (stat (fname1, &dummy) != 0) + error (_("No /proc directory: '%s'"), fname1); - printf_filtered (_("process %lld\n"), pid); + printf_filtered (_("process %lld\n"), pid); + } if (cmdline_f || all) { sprintf (fname1, "/proc/%lld/cmdline", pid); @@ -3693,65 +3771,7 @@ linux_nat_info_proc_cmd (char *args, int from_tty) } if (mappings_f || all) { - sprintf (fname1, "/proc/%lld/maps", pid); - if ((procfile = fopen (fname1, "r")) != NULL) - { - long long addr, endaddr, size, offset, inode; - char permissions[8], device[8], filename[MAXPATHLEN]; - struct cleanup *cleanup; - - cleanup = make_cleanup_fclose (procfile); - printf_filtered (_("Mapped address spaces:\n\n")); - if (gdbarch_addr_bit (current_gdbarch) == 32) - { - printf_filtered ("\t%10s %10s %10s %10s %7s\n", - "Start Addr", - " End Addr", - " Size", " Offset", "objfile"); - } - else - { - printf_filtered (" %18s %18s %10s %10s %7s\n", - "Start Addr", - " End Addr", - " Size", " Offset", "objfile"); - } - - while (read_mapping (procfile, &addr, &endaddr, &permissions[0], - &offset, &device[0], &inode, &filename[0])) - { - size = endaddr - addr; - - /* FIXME: carlton/2003-08-27: Maybe the printf_filtered - calls here (and possibly above) should be abstracted - out into their own functions? Andrew suggests using - a generic local_address_string instead to print out - the addresses; that makes sense to me, too. */ - - if (gdbarch_addr_bit (current_gdbarch) == 32) - { - printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n", - (unsigned long) addr, /* FIXME: pr_addr */ - (unsigned long) endaddr, - (int) size, - (unsigned int) offset, - filename[0] ? filename : ""); - } - else - { - printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n", - (unsigned long) addr, /* FIXME: pr_addr */ - (unsigned long) endaddr, - (int) size, - (unsigned int) offset, - filename[0] ? filename : ""); - } - } - - do_cleanups (cleanup); - } - else - warning (_("unable to open /proc file '%s'"), fname1); + target_print_proc_map (pid); } if (status_f || all) { @@ -4620,6 +4640,7 @@ linux_nat_add_target (struct target_ops *t) t->to_async_mask = linux_nat_async_mask; t->to_terminal_inferior = linux_nat_terminal_inferior; t->to_terminal_ours = linux_nat_terminal_ours; + t->to_print_proc_map = linux_nat_print_proc_map; /* Methods for non-stop support. */ t->to_stop = linux_nat_stop; diff --git a/gdb/target.c b/gdb/target.c index c16b55c..ad1a611 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -484,6 +484,7 @@ update_current_target (void) INHERIT (to_async_mask, t); INHERIT (to_find_memory_regions, t); INHERIT (to_make_corefile_notes, t); + INHERIT (to_print_proc_map, t); INHERIT (to_get_thread_local_address, t); INHERIT (to_can_execute_reverse, t); /* Do not inherit to_read_description. */ @@ -2501,6 +2502,13 @@ static char * dummy_make_corefile_notes (bfd *ignore1, int *ignore2) return NULL; } +/* Error-catcher for target_print_proc_map. */ +static void +dummy_print_proc_map (long long pid) +{ + error (_("No target.")); +} + /* Set up the handful of non-empty slots needed by the dummy target vector. */ @@ -2521,6 +2529,7 @@ init_dummy_target (void) dummy_target.to_stratum = dummy_stratum; dummy_target.to_find_memory_regions = dummy_find_memory_regions; dummy_target.to_make_corefile_notes = dummy_make_corefile_notes; + dummy_target.to_print_proc_map = dummy_print_proc_map; dummy_target.to_xfer_partial = default_xfer_partial; dummy_target.to_magic = OPS_MAGIC; } diff --git a/gdb/target.h b/gdb/target.h index 2722945..c763da5 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -428,6 +428,7 @@ struct target_ops void *), void *); char * (*to_make_corefile_notes) (bfd *, int *); + void (*to_print_proc_map) (long long); /* Return the thread-local address at OFFSET in the thread-local storage for the thread PTID and the shared library @@ -1057,6 +1058,12 @@ extern char *normal_pid_to_str (ptid_t ptid); #define target_make_corefile_notes(BFD, SIZE_P) \ (current_target.to_make_corefile_notes) (BFD, SIZE_P) +/* Print the memory-mapped information from the inferior + (or the corefile). */ + +#define target_print_proc_map(pid) \ + (current_target.to_print_proc_map) (pid) + /* Thread-local values. */ #define target_get_thread_local_address \ (current_target.to_get_thread_local_address)