--- ./gdb/gdbcore.h_orig 2024-11-04 03:02:25.504563690 -0600 +++ ./gdb/gdbcore.h 2024-11-04 03:13:26.336153986 -0600 @@ -29,6 +29,10 @@ #include "exec.h" #include "target.h" +/* Get the updated core_data after mmap */ + +extern void mmap_core (std::vector coreinfo_data); + /* Nonzero if there is a core file. */ extern int have_core_file_p (void); --- ./gdb/corelow.c_orig 2024-11-04 03:03:23.460896645 -0600 +++ ./gdb/corelow.c 2024-11-04 03:15:22.974379316 -0600 @@ -87,6 +87,8 @@ ULONGEST *xfered_len) override; void files_info () override; + void set_core_data_aix (std::vector core_data); + bool thread_alive (ptid_t ptid) override; const struct target_desc *read_description () override; @@ -171,6 +173,13 @@ struct gdbarch *m_core_gdbarch = NULL; }; +void +core_target::set_core_data_aix(std::vector core_data) +{ + m_core_section_table = core_data; +} + + core_target::core_target () { /* Find a first arch based on the BFD. We need the initial gdbarch so @@ -1448,6 +1457,16 @@ return dynamic_cast (proc_target); } +/* mmap core command */ +void +mmap_core (std::vector coreinfo_data) +{ + core_target *targ = get_current_core_target (); + if (targ != nullptr) + targ->set_core_data_aix (coreinfo_data); +} + + /* Display file backed mappings from core file. */ void --- ./gdb/Makefile.in_orig 2024-11-04 03:07:13.023331737 -0600 +++ ./gdb/Makefile.in 2024-11-04 03:07:34.629992491 -0600 @@ -1165,6 +1165,7 @@ memattr.c \ memory-map.c \ memrange.c \ + mmapfile.c \ memtag.c \ minidebug.c \ minsyms.c \ --- /dev/null 2025-09-22 02:45:00.832978957 -0500 +++ ./gdb/mmapfile.c 2025-09-22 02:33:34.126461173 -0500 @@ -0,0 +1,329 @@ +/* This implememts the mmapfile command for gdb */ + #include "defs.h" + #include "infcall.h" + #include "inferior.h" + #include "gdbcore.h" + #include "objfiles.h" + #include "solib.h" + #include "symfile.h" + #include "arch-utils.h" + #include "completer.h" + #include "cli/cli-decode.h" + #include + #include "regcache.h" + #include "regset.h" + #include "sys/mman.h" + #include "filenames.h" + #include "readline/tilde.h" + #include "gdbsupport/pathstuff.h" + #include "source.h" + #include "gdbsupport/filestuff.h" + #include "gdbsupport/gdb_vecs.h" + + #define core_bfd (current_program_space->cbfd.get ()) + + int count = 1; + typedef int mmap_openp_flags; + int mmap_fileopen(const char*, mmap_openp_flags, const char*, int, gdb::unique_xmalloc_ptr*); + + int + mmap_fileopen (const char *path, mmap_openp_flags opts, const char *string, + int mode, gdb::unique_xmalloc_ptr *filename_opened) + { + int fd; + char *filename; + int alloclen; + /* The errno set for the last name we tried to open (and + failed). */ + int last_errno = 0; + std::vector> dir_vec; + + /* The open syscall MODE parameter is not specified. */ + gdb_assert ((mode & O_CREAT) == 0); + gdb_assert (string != NULL); + + /* A file with an empty name cannot possibly exist. Report a failure + without further checking. + + This is an optimization which also defends us against buggy + implementations of the "stat" function. For instance, we have + noticed that a MinGW debugger built on Windows XP 32bits crashes + when the debugger is started with an empty argument. */ + if (string[0] == '\0') + { + errno = ENOENT; + return -1; + } + + if (!path) + path = "."; + + if ((opts & 0x01) || IS_ABSOLUTE_PATH (string)) //OPF_TRY_CWD_FIRST 0x01 + { + int i; + + filename = (char *) alloca (strlen (string) + 1); + strcpy (filename, string); + fd = open (filename, O_RDONLY); + if (fd >= 0) + goto done; + last_errno = errno; + + if (!(opts & 0x02))//OPF_SEARCH_IN_PATH + for (i = 0; string[i]; i++) + if (IS_DIR_SEPARATOR (string[i])) + goto done; + } + + /* For dos paths, d:/foo -> /foo, and d:foo -> foo. */ + if (HAS_DRIVE_SPEC (string)) + string = STRIP_DRIVE_SPEC (string); + + /* /foo => foo, to avoid multiple slashes that Emacs doesn't like. */ + while (IS_DIR_SEPARATOR(string[0])) + string++; + + /* ./foo => foo */ + while (string[0] == '.' && IS_DIR_SEPARATOR (string[1])) + string += 2; + + alloclen = strlen (path) + strlen (string) + 2; + filename = (char *) alloca (alloclen); + fd = -1; + last_errno = ENOENT; + dir_vec = dirnames_to_char_ptr_vec (path); + + for (const gdb::unique_xmalloc_ptr &this_dir_up : dir_vec) + { + const char *this_dir = this_dir_up.get (); + size_t len = strlen (this_dir); + int reg_file_errno; + + if (strcmp (this_dir, "$cwd") == 0) + { + /* Name is $cwd -- insert current directory name instead. */ + int newlen; + + /* First, realloc the filename buffer if too short. */ + len = strlen (current_directory); + newlen = len + strlen (string) + 2; + if (newlen > alloclen) + { + alloclen = newlen; + filename = (char *) alloca (alloclen); + } + strcpy (filename, current_directory); + } + else if (strchr(this_dir, '~')) + { + /* See whether we need to expand the tilde. */ + int newlen; + + gdb::unique_xmalloc_ptr tilde_expanded (tilde_expand (this_dir)); + + /* First, realloc the filename buffer if too short. */ + len = strlen (tilde_expanded.get ()); + newlen = len + strlen (string) + 2; + if (newlen > alloclen) + { + alloclen = newlen; + filename = (char *) alloca (alloclen); + } + strcpy (filename, tilde_expanded.get ()); + } + else + { + /* Normal file name in path -- just use it. */ + strcpy (filename, this_dir); + + /* Don't search $cdir. It's also a magic path like $cwd, but we + don't have enough information to expand it. The user *could* + have an actual directory named '$cdir' but handling that would + be confusing, it would mean different things in different + contexts. If the user really has '$cdir' one can use './$cdir'. + We can get $cdir when loading scripts. When loading source files + $cdir must have already been expanded to the correct value. */ + if (strcmp (this_dir, "$cdir") == 0) + continue; + } + + /* Remove trailing slashes. */ + while (len > 0 && IS_DIR_SEPARATOR (filename[len - 1])) + filename[--len] = 0; + + strcat (filename + len, SLASH_STRING); + strcat (filename, string); + + if (is_regular_file (filename, ®_file_errno)) + { + fd = open (filename, O_RDONLY); + if (fd >= 0) + break; + last_errno = errno; + } + else + last_errno = reg_file_errno; + } + + done: + if (filename_opened) + { + /* If a file was opened, canonicalize its filename. */ + gdb::unique_xmalloc_ptr mmap_filename_opened; + if (fd < 0) + *filename_opened = NULL; + else if ((opts & 0x04) != 0) //OPF_RETURN_REALPATH 0x04 + *filename_opened = gdb_realpath (filename); + else + *filename_opened = gdb_realpath (filename); + } + + errno = last_errno; + return fd; + } + + static void + mmap_command (const char *args, int from_tty) + { + openp_flag TRY_CWD = OPF_TRY_CWD_FIRST; + openp_flag RETURN_REALPATH = OPF_RETURN_REALPATH; + CORE_ADDR addr; + std::vector mmap_data; + asection *sec, *vmsec; + int fd, flags; + char *mmapsec_name, *sec_name; + gdb::unique_xmalloc_ptr file_pathname; + + off64_t offset = 0; + caddr_t vaddr = NULL; + size_t size = 0; + int i = 0; + char *arg[4]; + + + arg[i] = strtok (args," "); + + while (arg[i++] != NULL) + arg[i] = strtok (NULL, " "); + + /* Check if the parameters entered by the user are correct in number and format */ + + if (i != 5) + error (_("MMAP ERROR: Usage: mmapfile \ + ")); + + /* No point using mmap if gdb is not debugging a core */ + + if (core_bfd == NULL) + error (_("MMAP ERROR: No core file loaded.")); + + /* Find out if the user entered offset and size in base 16 or base 10 */ + + if (arg[2][0] == '0' && arg[2][1] == 'x') + offset = strtoll(arg[2], NULL, 16); + else + offset = strtoll(arg[2], NULL, 10); + + if (arg[3][0] == '0' && arg[3][1] == 'x') + size = strtoll(arg[3], NULL, 16); + else + size = strtoll(arg[3], NULL, 10); + + addr = parse_and_eval_address (arg[1]); + + /* Check if the desired mmap address overlaps with an already existing + virtual memory address in the core. If so, then display error */ + + vmsec = bfd_get_section_by_name(core_bfd, ".vmdata"); + + gdb::unique_xmalloc_ptr expanded_name (tilde_expand (arg[0])); + + while (vmsec != NULL) + { + if (addr >= vmsec->vma && addr < (vmsec->vma + vmsec->size)) + + error(_("MMAP_ERROR:\nCannot memory map file <%s> at\n\ + address 0x%15.lX as it results in an overlap\nuse info target for more info"), arg[0], addr); + + + if (strcmp (vmsec->next->name, ".vmdata") == 0) + vmsec = vmsec->next; + else + vmsec = NULL; + } + + if (size == 0) + error (_("MMAP ERROR: size cannot be 0")); + + /* Get file descriptor for the desired file to be mmaped */ + + fd = mmap_fileopen (getenv("PATH"), + TRY_CWD | RETURN_REALPATH, + expanded_name.get (), + O_RDONLY, + &file_pathname); + if (fd < 0) + perror_with_name (arg[0]); + + flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY; + + /* mmap the given file to the desired address/symbol and let vaddr point to it */ + + vaddr = (char *)mmap((void *)addr, size, PROT_READ, MAP_FIXED | MAP_SHARED, fd, offset); + + if ((long) vaddr == -1) + error(_("MMAP_ERROR:\nCannot memory map file <%s> at\n\ + address 0x%15.lX as it results in an overlap\nuse info target for more info"), arg[0], addr); + + /* Get a unique section name and assign it to the new section created in the core */ + + mmapsec_name = bfd_get_unique_section_name (core_bfd, "mmap_section", &count); + + sec_name = (unsigned char *)malloc (snprintf (NULL, 0, "%s (Mapped to %s)", mmapsec_name, file_pathname.get())); + + sprintf(sec_name, "%s (Mapped to %s)", mmapsec_name, file_pathname.get()); + + /* Create a new section in the core_bfd with this unique section name */ + + sec = bfd_make_section_anyway_with_flags (core_bfd, sec_name, flags); + + /* Fill out the required section contents */ + + sec->contents = (unsigned char*) vaddr; + bfd_set_section_vma (sec, (unsigned long int)vaddr); + bfd_set_section_alignment (sec, 0); + bfd_set_section_size (sec, size); + + /* Build a new section table which has contains all the sections present + in core_bfd and also the newly created mmap section */ + + //mmap_data = new target_section_table; + + mmap_data = build_section_table (current_program_space->cbfd.get ()); + + close(fd); + mmap_core (mmap_data); + gdb_printf (_("File %s is now mapped\nfrom address %lX to %lX.\n"), file_pathname.get(), addr, addr+ size); + } + + /* Implement mmap command and add it to the commands list */ + + // extern initialize_file_ftype _initialize_mmap; + +INIT_GDB_FILE (mmapfile) +{ + const char *add_cmd = "mmapfile"; + struct cmd_list_element *c = add_com(add_cmd, class_vars, mmap_command, _("\ +Add contents of memory mapped files missing from core dump.\n\n\ +Usage:\nmmapfile \n\ +Command is used (mostly while debugging a core) if the core file sections do not contain\n\ +memory mapped regions under the vmdata section.\n\ +This happens if files are mmap-ed with MMAP_PRIVATE/MAP_SHARED and RO permissions.\n\ +Using this command, the user can access data from\n\ +the mmap-ed files, which are missing from the core file.")); + +set_cmd_completer (c, NULL); +add_com_alias ("mmap", c, class_files, 1); +} + +