From patchwork Fri Jan 20 18:17:53 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Weigand X-Patchwork-Id: 6332 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id AB08E23E81 for ; Fri, 20 Jan 2012 18:18:01 +0000 (UTC) Received: from mail-bk0-f52.google.com (mail-bk0-f52.google.com [209.85.214.52]) by fiordland.canonical.com (Postfix) with ESMTP id 90DC1A181F7 for ; Fri, 20 Jan 2012 18:18:01 +0000 (UTC) Received: by bkar19 with SMTP id r19so771714bka.11 for ; Fri, 20 Jan 2012 10:18:01 -0800 (PST) Received: by 10.204.10.73 with SMTP id o9mr6681852bko.99.1327083480018; Fri, 20 Jan 2012 10:18:00 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.205.82.144 with SMTP id ac16cs13202bkc; Fri, 20 Jan 2012 10:17:59 -0800 (PST) Received: by 10.213.32.7 with SMTP id a7mr565282ebd.109.1327083478546; Fri, 20 Jan 2012 10:17:58 -0800 (PST) Received: from e06smtp11.uk.ibm.com (e06smtp11.uk.ibm.com. [195.75.94.107]) by mx.google.com with ESMTPS id n54si2382496eea.9.2012.01.20.10.17.58 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 20 Jan 2012 10:17:58 -0800 (PST) Received-SPF: pass (google.com: domain of uweigand@de.ibm.com designates 195.75.94.107 as permitted sender) client-ip=195.75.94.107; Authentication-Results: mx.google.com; spf=pass (google.com: domain of uweigand@de.ibm.com designates 195.75.94.107 as permitted sender) smtp.mail=uweigand@de.ibm.com Received: from /spool/local by e06smtp11.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 20 Jan 2012 18:17:58 -0000 Received: from d06nrmr1407.portsmouth.uk.ibm.com (9.149.38.185) by e06smtp11.uk.ibm.com (192.168.101.141) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 20 Jan 2012 18:17:55 -0000 Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by d06nrmr1407.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q0KIHsCh2101476 for ; Fri, 20 Jan 2012 18:17:54 GMT Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q0KIHsRP015969 for ; Fri, 20 Jan 2012 11:17:54 -0700 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id q0KIHrT7015902 for ; Fri, 20 Jan 2012 11:17:53 -0700 Message-Id: <201201201817.q0KIHrT7015902@d06av02.portsmouth.uk.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Fri, 20 Jan 2012 19:17:53 +0100 Subject: Re: [rfc v2][3/3] Remote core file generation: memory map To: patches@linaro.org Date: Fri, 20 Jan 2012 19:17:53 +0100 (CET) From: "Ulrich Weigand" X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 x-cbid: 12012018-5024-0000-0000-000001778D43 http://sourceware.org/ml/gdb-patches/2012-01/msg00725.html > this patch replaces the earlier attempt to define a XML-based > target object in order to implement find_memory_regions for remote targets. > > Instead, we simply move find_memory_regions to target-dependent code, and > access /proc via the new TARGET_OBJECT_PROC target object. /proc/../maps > parsing code is once again shared with the info_proc implementation which > is now also in linux-tdep.c. > > For procfs targets, we still fall back to the target method. Here's the version of the patch I just checked in. It is basically unchanged compared to the prior version, execpt it uses target_fileio_... to access /proc files instead of TARGET_OBJECT_PROC. Bye, Ulrich ChangeLog: * gdbarch.sh (find_memory_regions): New callback. * gdbarch.c, gdbarch.h: Regenerate. * gcore.c (gcore_memory_sections): Try gdbarch find_memory_regions callback before falling back to target method. * linux-nat.c (read_mapping, linux_nat_find_memory_regions): Remove. (linux_target_install_ops): No longer install it. * linux-tdep.c (linux_find_memory_regions): New function. (linux_init_abi): Install it. Index: gdb-head/gdb/gcore.c =================================================================== --- gdb-head.orig/gdb/gcore.c 2012-01-19 10:45:56.000000000 +0100 +++ gdb-head/gdb/gcore.c 2012-01-19 10:45:59.000000000 +0100 @@ -561,8 +561,14 @@ gcore_copy_callback (bfd *obfd, asection static int gcore_memory_sections (bfd *obfd) { - if (target_find_memory_regions (gcore_create_callback, obfd) != 0) - return 0; /* FIXME: error return/msg? */ + /* Try gdbarch method first, then fall back to target method. */ + if (!gdbarch_find_memory_regions_p (target_gdbarch) + || gdbarch_find_memory_regions (target_gdbarch, + gcore_create_callback, obfd) != 0) + { + if (target_find_memory_regions (gcore_create_callback, obfd) != 0) + return 0; /* FIXME: error return/msg? */ + } /* Record phdrs for section-to-segment mapping. */ bfd_map_over_sections (obfd, make_output_phdrs, NULL); Index: gdb-head/gdb/gdbarch.c =================================================================== --- gdb-head.orig/gdb/gdbarch.c 2012-01-19 10:45:56.000000000 +0100 +++ gdb-head/gdb/gdbarch.c 2012-01-19 10:45:59.000000000 +0100 @@ -240,6 +240,7 @@ struct gdbarch gdbarch_regset_from_core_section_ftype *regset_from_core_section; struct core_regset_section * core_regset_sections; gdbarch_make_corefile_notes_ftype *make_corefile_notes; + gdbarch_find_memory_regions_ftype *find_memory_regions; gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries; gdbarch_core_pid_to_str_ftype *core_pid_to_str; const char * gcore_bfd_target; @@ -397,6 +398,7 @@ struct gdbarch startup_gdbarch = 0, /* regset_from_core_section */ 0, /* core_regset_sections */ 0, /* make_corefile_notes */ + 0, /* find_memory_regions */ 0, /* core_xfer_shared_libraries */ 0, /* core_pid_to_str */ 0, /* gcore_bfd_target */ @@ -686,6 +688,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of fetch_pointer_argument, has predicate. */ /* Skip verify of regset_from_core_section, has predicate. */ /* Skip verify of make_corefile_notes, has predicate. */ + /* Skip verify of find_memory_regions, has predicate. */ /* Skip verify of core_xfer_shared_libraries, has predicate. */ /* Skip verify of core_pid_to_str, has predicate. */ /* Skip verify of gcore_bfd_target, has predicate. */ @@ -928,6 +931,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s "gdbarch_dump: fetch_tls_load_module_address = <%s>\n", host_address_to_string (gdbarch->fetch_tls_load_module_address)); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_find_memory_regions_p() = %d\n", + gdbarch_find_memory_regions_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: find_memory_regions = <%s>\n", + host_address_to_string (gdbarch->find_memory_regions)); + fprintf_unfiltered (file, "gdbarch_dump: float_bit = %s\n", plongest (gdbarch->float_bit)); fprintf_unfiltered (file, @@ -3278,6 +3287,30 @@ set_gdbarch_make_corefile_notes (struct } int +gdbarch_find_memory_regions_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->find_memory_regions != NULL; +} + +int +gdbarch_find_memory_regions (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->find_memory_regions != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_find_memory_regions called\n"); + return gdbarch->find_memory_regions (gdbarch, func, data); +} + +void +set_gdbarch_find_memory_regions (struct gdbarch *gdbarch, + gdbarch_find_memory_regions_ftype find_memory_regions) +{ + gdbarch->find_memory_regions = find_memory_regions; +} + +int gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); Index: gdb-head/gdb/gdbarch.h =================================================================== --- gdb-head.orig/gdb/gdbarch.h 2012-01-19 10:45:56.000000000 +0100 +++ gdb-head/gdb/gdbarch.h 2012-01-19 10:45:59.000000000 +0100 @@ -717,6 +717,14 @@ typedef char * (gdbarch_make_corefile_no extern char * gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size); extern void set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch, gdbarch_make_corefile_notes_ftype *make_corefile_notes); +/* Find core file memory regions */ + +extern int gdbarch_find_memory_regions_p (struct gdbarch *gdbarch); + +typedef int (gdbarch_find_memory_regions_ftype) (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data); +extern int gdbarch_find_memory_regions (struct gdbarch *gdbarch, find_memory_region_ftype func, void *data); +extern void set_gdbarch_find_memory_regions (struct gdbarch *gdbarch, gdbarch_find_memory_regions_ftype *find_memory_regions); + /* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from core file into buffer READBUF with length LEN. */ Index: gdb-head/gdb/gdbarch.sh =================================================================== --- gdb-head.orig/gdb/gdbarch.sh 2012-01-19 10:45:56.000000000 +0100 +++ gdb-head/gdb/gdbarch.sh 2012-01-19 10:45:59.000000000 +0100 @@ -634,6 +634,9 @@ v:struct core_regset_section *:core_regs # Create core file notes M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size +# Find core file memory regions +M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data + # Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from # core file into buffer READBUF with length LEN. M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len Index: gdb-head/gdb/linux-nat.c =================================================================== --- gdb-head.orig/gdb/linux-nat.c 2012-01-19 10:45:56.000000000 +0100 +++ gdb-head/gdb/linux-nat.c 2012-01-19 10:45:59.000000000 +0100 @@ -4396,90 +4396,6 @@ linux_child_pid_to_exec_file (int pid) return name1; } -/* Service function for corefiles and info proc. */ - -static int -read_mapping (FILE *mapfile, - long long *addr, - long long *endaddr, - char *permissions, - long long *offset, - char *device, long long *inode, char *filename) -{ - int ret = fscanf (mapfile, "%llx-%llx %s %llx %s %llx", - addr, endaddr, permissions, offset, device, inode); - - filename[0] = '\0'; - if (ret > 0 && ret != EOF) - { - /* Eat everything up to EOL for the filename. This will prevent - weird filenames (such as one with embedded whitespace) from - confusing this code. It also makes this code more robust in - respect to annotations the kernel may add after the filename. - - Note the filename is used for informational purposes - only. */ - ret += fscanf (mapfile, "%[^\n]\n", filename); - } - - return (ret != 0 && ret != EOF); -} - -/* Fills the "to_find_memory_regions" target vector. Lists the memory - regions in the inferior for a corefile. */ - -static int -linux_nat_find_memory_regions (find_memory_region_ftype func, void *obfd) -{ - int pid = PIDGET (inferior_ptid); - char mapsfilename[MAXPATHLEN]; - FILE *mapsfile; - long long addr, endaddr, size, offset, inode; - char permissions[8], device[8], filename[MAXPATHLEN]; - int read, write, exec; - struct cleanup *cleanup; - - /* Compose the filename for the /proc memory map, and open it. */ - sprintf (mapsfilename, "/proc/%d/maps", pid); - if ((mapsfile = fopen (mapsfilename, "r")) == NULL) - error (_("Could not open %s."), mapsfilename); - cleanup = make_cleanup_fclose (mapsfile); - - if (info_verbose) - fprintf_filtered (gdb_stdout, - "Reading memory regions from %s\n", mapsfilename); - - /* Now iterate until end-of-file. */ - while (read_mapping (mapsfile, &addr, &endaddr, &permissions[0], - &offset, &device[0], &inode, &filename[0])) - { - size = endaddr - addr; - - /* Get the segment's permissions. */ - read = (strchr (permissions, 'r') != 0); - write = (strchr (permissions, 'w') != 0); - exec = (strchr (permissions, 'x') != 0); - - if (info_verbose) - { - fprintf_filtered (gdb_stdout, - "Save segment, %s bytes at %s (%c%c%c)", - plongest (size), paddress (target_gdbarch, addr), - read ? 'r' : ' ', - write ? 'w' : ' ', exec ? 'x' : ' '); - if (filename[0]) - fprintf_filtered (gdb_stdout, " for %s", filename); - fprintf_filtered (gdb_stdout, "\n"); - } - - /* Invoke the callback function to create the corefile - segment. */ - func (addr, size, read, write, exec, obfd); - } - do_cleanups (cleanup); - return 0; -} - /* Records the thread's register state for the corefile note section. */ @@ -4827,7 +4743,6 @@ linux_target_install_ops (struct target_ t->to_post_startup_inferior = linux_child_post_startup_inferior; t->to_post_attach = linux_child_post_attach; t->to_follow_fork = linux_child_follow_fork; - t->to_find_memory_regions = linux_nat_find_memory_regions; t->to_make_corefile_notes = linux_nat_make_corefile_notes; super_xfer_partial = t->to_xfer_partial; Index: gdb-head/gdb/linux-tdep.c =================================================================== --- gdb-head.orig/gdb/linux-tdep.c 2012-01-19 10:45:56.000000000 +0100 +++ gdb-head/gdb/linux-tdep.c 2012-01-19 10:45:59.000000000 +0100 @@ -530,6 +530,53 @@ linux_info_proc (struct gdbarch *gdbarch } } +/* List memory regions in the inferior for a corefile. */ + +static int +linux_find_memory_regions (struct gdbarch *gdbarch, + find_memory_region_ftype func, void *obfd) +{ + char filename[100]; + gdb_byte *data; + + /* We need to know the real target PID to access /proc. */ + if (current_inferior ()->fake_pid_p) + return 1; + + xsnprintf (filename, sizeof filename, + "/proc/%d/maps", current_inferior ()->pid); + data = target_fileio_read_stralloc (filename); + if (data) + { + struct cleanup *cleanup = make_cleanup (xfree, data); + char *line; + + for (line = strtok (data, "\n"); line; line = strtok (NULL, "\n")) + { + ULONGEST addr, endaddr, offset, inode; + const char *permissions, *device, *filename; + size_t permissions_len, device_len; + int read, write, exec; + + read_mapping (line, &addr, &endaddr, &permissions, &permissions_len, + &offset, &device, &device_len, &inode, &filename); + + /* Decode permissions. */ + read = (memchr (permissions, 'r', permissions_len) != 0); + write = (memchr (permissions, 'w', permissions_len) != 0); + exec = (memchr (permissions, 'x', permissions_len) != 0); + + /* Invoke the callback function to create the corefile segment. */ + func (addr, endaddr - addr, read, write, exec, obfd); + } + + do_cleanups (cleanup); + return 0; + } + + return 1; +} + /* Determine which signal stopped execution. */ static int @@ -807,6 +854,7 @@ linux_init_abi (struct gdbarch_info info { set_gdbarch_core_pid_to_str (gdbarch, linux_core_pid_to_str); set_gdbarch_info_proc (gdbarch, linux_info_proc); + set_gdbarch_find_memory_regions (gdbarch, linux_find_memory_regions); set_gdbarch_make_corefile_notes (gdbarch, linux_make_corefile_notes_1); }