)]}'
{
  "commit": "fcfd8a4f2392d3882c07c4e127bfcfb53ca78728",
  "tree": "5400806e992b5fe0755d1a9c2c038ba1c47ec4f5",
  "parents": [
    "a8f4696286aa48c8c5df6569c10036eaa980c0b2"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Wed May 07 12:58:41 2025 +0100"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Tue Jun 03 11:57:47 2025 +0100"
  },
  "message": "gdb: support zero inode in generate-core-file command\n\nIt is possible, when creating a shared memory segment (i.e. with\nshmget), that the id of the segment will be zero.\n\nWhen looking at the segment in /proc/PID/smaps, the inode field of the\nentry holds the shared memory segment id.\n\nAnd so, it can be the case that an entry (in the smaps file) will have\nan inode of zero.\n\nWhen GDB generates a core file, with the generate-core-file (or its\ngcore alias) command, the shared memory segment should be written into\nthe core file.\n\nFedora GDB has, since 2008, carried a patch that tests this case.\nThere is no fix for GDB associated with the test, and unfortunately,\nthe motivation for the test has been lost to the mists of time.  This\nlikely means that a fix was merged upstream without a suitable test,\nbut I\u0027ve not been able to find and relevant commit.  The test seems to\nbe checking that the shared memory segment with id zero, is being\nwritten to the core file.\n\nWhile looking at this test and trying to work out if it should be\nposted upstream, I saw that GDB does appear to write the shared memory\nsegment into the core file (as expected), which is good.  However, GDB\nstill isn\u0027t getting this case exactly right, there appears to be no\nNT_FILE entry for the shared memory mapping if the mapping had an id\nof zero.\n\nIn gcore_memory_sections (gcore.c) we call back into linux-tdep.c (via\nthe gdbarch_find_memory_regions call) to correctly write the shared\nmemory segment into the core file, however, in\nlinux_make_mappings_corefile_notes, when we use\nlinux_find_memory_regions_full to create the NT_FILE note, we call\nback in to dump_note_entry_p for each mapping, and in here we reject\nany mapping with a zero inode.\n\nThe result of this, is that, for a shared memory segment with a\nnon-zero id, after loading the core file, the shared memory segment\nwill appear in the \u0027proc info mappings\u0027 output.  But, for a shared\nmemory segment with a zero id, the segment will not appear in the\n\u0027proc info mappings\u0027 output.\n\nI initially tried just dropping the inode check in this function (see\nprevious commit 1e21c846c27, which I then reverted in commit\n998165ba99a.\n\nThe problem with dropping the inode check is that the special kernel\nmappings, e.g. \u0027[vvar]\u0027 would now get a NT_FILE entry.  In fact, any\nspecial entry except \u0027[vdso]\u0027 and \u0027[vsyscall]\u0027 which are specifically\nchecked for in dump_note_entry_p would get a NT_FILE entry, which is\nnot correct.\n\nSo, instead, I propose that if the inode is zero, and the filename\nstarts with \u0027[\u0027 and finished with \u0027]\u0027 then we should not create a\nNT_FILE entry.  But otherwise a zero inode should not prevent a\nNT_FILE entry being created.\n\nThe test for this change is a bit tricky.  The original Fedora\ntest (mentioned above) has a loop that tries to grab the shared memory\nmapping with id zero.  This was, unfortunately, not very reliable.\n\nI tried to make this more reliable by going multi-threaded, and\nwaiting for longer, see my proposal here:\n\n  https://inbox.sourceware.org/gdb-patches/0d389b435cbb0924335adbc9eba6cf30b4a2c4ee.1741776651.git.aburgess@redhat.com\n\nBut this was still not great.  On further testing this was only\npassing (i.e. managing to find the shared memory mapping with id zero)\nabout 60% of the time.\n\nHowever, I realised that GDB finds the shared memory id by reading the\n/proc/PID/smaps file.  But we don\u0027t really _need_ the shared memory id\nfor anything, we just use the value (as an inode) to decide if the\nsegment should be included in the core file or not.  The id isn\u0027t even\nwritten to the core file.  So, if we could intercept the read of the\nsmaps file, then maybe, we could lie to GDB, and tell it that the id\nwas zero, and then see how GDB handles this.\n\nAnd luckily, we can do that using a preload library!\n\nWe already have a test that uses a preload library to modify GDB, see\ngdb.threads/attach-slow-waitpid.exp.\n\nSo, I have created a new preload library.  This one intercepts open,\nopen64, close, read, and pread.  When GDB attempts to open\n/proc/PID/smaps, the library spots this and loads the file contents\ninto a memory buffer.  The buffer is then modified to change the id of\nany shared memory mapping to zero.  Any reads from this file are\nserved from the modified memory buffer.\n\nI tested on x86-64, AArch64, PPC, s390, and ARM, all running various\nversions of GNU/Linux.  The requirement for open64() came from my ARM\ntesting.  The other targets used plain open().\n\nAnd so, the test is now simple.  Start GDB with the preload library in\nplace, start the inferior and generate a core file.  Then restart GDB,\nload the core file, and check the shared memory mapping was included.\nThis test will fail with an unpatched GDB, and succeed with the patch\napplied.\n\nTested-By: Guinevere Larsen \u003cguinevere@redhat.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "0b08e1290c2bfaf93bb0354786da84affdcc645b",
      "old_mode": 33188,
      "old_path": "gdb/linux-tdep.c",
      "new_id": "1e339b59e2e8caba57771211f0bb400666d30dba",
      "new_mode": 33188,
      "new_path": "gdb/linux-tdep.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "58fdec653b15d0b1e6faa300e6052e59c69dc90f",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/corefile-shmem-zero-id-lib.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "92d2edfdd4154a87341ed65f54c7f5f212680b4c",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/corefile-shmem-zero-id.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "57c665e9e4c405ca0db69fdcb499e68b3b845324",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/corefile-shmem-zero-id.exp"
    }
  ]
}
