)]}'
{
  "commit": "9335533438ea55497e0bc88e4c0cf3e240337caa",
  "tree": "4cde606ac092af9d53438b72bac9bfb657d0d36e",
  "parents": [
    "84d16757719ca263cea4dc2df496223c0efa740b"
  ],
  "author": {
    "name": "Matt Turner",
    "email": "mattst88@gmail.com",
    "time": "Wed Aug 26 16:27:01 2026 -0400"
  },
  "committer": {
    "name": "Alan Modra",
    "email": "amodra@gmail.com",
    "time": "Thu Aug 27 09:25:16 2026 +0930"
  },
  "message": "alpha: allocate .got contents after relaxation has sized them\n\nelf64_alpha_early_size_sections sizes and merges the .got subsections and\nthen allocates each one\u0027s contents buffer.  elf64_alpha_relax_section runs\nafterwards and calls elf64_alpha_size_got_sections again with may_merge\ntrue.  That re-merge zeroes and recomputes every subsection size, and it\ncan make a subsection larger than it was when its buffer was allocated.\nThe comment there asserts that \"relaxation only shrinks the table\", which\nis true of the table as a whole but not of an individual subsection: a\nmerge moves entries into one subsection and empties another.\n\nRelaxation is not limited to --relax links.  ld/emultempl/alphaelf.em\nenables it for -O as well, so an ordinary distribution build using\n-Wl,-O1 takes this path.\n\nWhen a subsection grows, elf64_alpha_relocate_section writes GOT slots past\nthe end of the allocated buffer, corrupting whatever objalloc placed after\nit.  Linking a large C++ shared library with -Bsymbolic or\n-Bsymbolic-functions aborts ld with a glibc \"free(): invalid next size\", or\nproduces a library whose .rela.dyn is corrupt and which faults at run time\nwith a GOT slot holding an unrelated pointer.  In one instance a .got\nallocated at 57664 bytes grew to 64840, still under the 64K cap so nothing\ndiagnosed it, and 1796 slot writes fell outside the buffer.\n\nRather than resizing the buffers whenever relaxation re-runs the sizing,\nwhich would throw away the previous allocation on every relaxation trip,\nallocate them once from elf64_alpha_final_link, by which point the sizes\nhave settled.  Nothing reads or writes the got before then.\n\nThe .got subsection of the dynobj was allocated a second time by\nelf64_alpha_late_size_sections, along with the real dynamic sections; that\nallocation has the same problem and is dropped too.  The other sections\nthat loop walks are only shrunk by relaxation, so the space allocated for\nthem there stays big enough.\n\nRoute the got slot writes through a new alpha_got_slot, which asserts that\nthe subsection has had its contents allocated and that the slot lies inside\nit.  The assertions do not prevent the write, but they turn a future sizing\nmistake of this kind into a reported one rather than a silent overrun.\n\nThe test needs the two subsections to be unmergeable when they are first\nsized and mergeable once relaxation has dropped some entries, so it pairs\nan object holding 8000 entries against preemptible symbols with one whose\n250 entries include 150 that relaxation removes.  Without the fix it\nreproduces both symptoms: the assertion fires and glibc aborts the link.\n\n\t* elf64-alpha.c (alpha_got_slot): New function.\n\t(elf64_alpha_early_size_sections): Don\u0027t allocate the .got\n\tsubsection contents here.\n\t(elf64_alpha_late_size_sections): Don\u0027t allocate .got here either.\n\t(elf64_alpha_relax_section): Correct stale comment.\n\t(elf64_alpha_final_link): Allocate the .got subsection contents.\n\t(elf64_alpha_relocate_section): Use alpha_got_slot.\n\t(elf64_alpha_finish_dynamic_symbol): Likewise.\n\nld/\n\t* testsuite/ld-alpha/got-realloc-a.s: New test.\n\t* testsuite/ld-alpha/got-realloc-b.s: New test.\n\t* testsuite/ld-alpha/got-realloc.rd: New test.\n\t* testsuite/ld-alpha/alpha.exp: Run it.\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "c43d427989ddb099aac37890baabc7d447774e5f",
      "old_mode": 33188,
      "old_path": "bfd/elf64-alpha.c",
      "new_id": "8b8a97a4b0595db24fa1a32ffe35e4c277375fd0",
      "new_mode": 33188,
      "new_path": "bfd/elf64-alpha.c"
    },
    {
      "type": "modify",
      "old_id": "f6b16918927ed00f8a222c5a6c49f94f77491ace",
      "old_mode": 33188,
      "old_path": "ld/testsuite/ld-alpha/alpha.exp",
      "new_id": "af5d94e24a8c884e77d2136bc38b78bf1b9e344a",
      "new_mode": 33188,
      "new_path": "ld/testsuite/ld-alpha/alpha.exp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "607604130b5b0b8dadc0099e65f069bcf5d96b78",
      "new_mode": 33188,
      "new_path": "ld/testsuite/ld-alpha/got-realloc-a.s"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "4ce760ace1f49ee5c17862da2dfbb32bf73bee58",
      "new_mode": 33188,
      "new_path": "ld/testsuite/ld-alpha/got-realloc-b.s"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "75f75262eb1104b72dc94945f9e1a97dcd386c3f",
      "new_mode": 33188,
      "new_path": "ld/testsuite/ld-alpha/got-realloc.rd"
    }
  ]
}
