)]}'
{
  "commit": "0cd846f24fc705daadb51e2cba3f28b975ddadf6",
  "tree": "b20532dff2dc62be730ea76d6c40ad6cde1f755d",
  "parents": [
    "74161f485b5d54fe963cbd3d081b718ec84d2e00"
  ],
  "author": {
    "name": "Adam Langley",
    "email": "alangley@gmail.com",
    "time": "Tue Jul 14 17:00:48 2020 -0700"
  },
  "committer": {
    "name": "CQ bot account: commit-bot@chromium.org",
    "email": "commit-bot@chromium.org",
    "time": "Mon Aug 10 23:46:33 2020 +0000"
  },
  "message": "delocation: large memory model support.\n\nLarge memory models on x86-64 allow the code/data of a shared object /\nexecutable to be larger than 2GiB. This is typically impossible because\nx86-64 code frequently uses int32 offsets from RIP.\n\nConsider the following program:\n\n    int getpid();\n\n    int main() {\n        return getpid();\n    }\n\nThis is turned into the following assembly under a large memory model:\n\n.L0$pb:\n\tleaq\t.L0$pb(%rip), %rax\n\tmovabsq\t$_GLOBAL_OFFSET_TABLE_-.L0$pb, %rcx\n\taddq\t%rax, %rcx\n\tmovabsq\t$getpid@GOT, %rdx\n\txorl\t%eax, %eax\n\tjmpq\t*(%rcx,%rdx)            # TAILCALL\n\nAnd, with relocations:\n\n   0:\t48 8d 05 f9 ff ff ff \tlea    -0x7(%rip),%rax        # 0 \u003cmain\u003e\n   7:\t48 b9 00 00 00 00 00 \tmovabs $0x0,%rcx\n   e:\t00 00 00\n\t\t\t9: R_X86_64_GOTPC64\t_GLOBAL_OFFSET_TABLE_+0x9\n  11:\t48 01 c1             \tadd    %rax,%rcx\n  14:\t48 ba 00 00 00 00 00 \tmovabs $0x0,%rdx\n  1b:\t00 00 00\n\t\t\t16: R_X86_64_GOT64\tgetpid\n  1e:\t31 c0                \txor    %eax,%eax\n  20:\tff 24 11             \tjmpq   *(%rcx,%rdx,1)\n\nWe can see that, in the large memory model, function calls involve\nloading the address of _GLOBAL_OFFSET_TABLE_ (using `movabs`, which\ntakes a 64-bit immediate) and then indexing into it. Both cause\nrelocations.\n\nIf we link the binary and disassemble we get:\n\n0000000000001120 \u003cmain\u003e:\n    1120:\t48 8d 05 f9 ff ff ff \tlea    -0x7(%rip),%rax        # 1120 \u003cmain\u003e\n    1127:\t48 b9 e0 2e 00 00 00 \tmovabs $0x2ee0,%rcx\n    112e:\t00 00 00\n    1131:\t48 01 c1             \tadd    %rax,%rcx\n    1134:\t48 ba d8 ff ff ff ff \tmovabs $0xffffffffffffffd8,%rdx\n    113b:\tff ff ff\n    113e:\t31 c0                \txor    %eax,%eax\n    1140:\tff 24 11             \tjmpq   *(%rcx,%rdx,1)\n\nThus the _GLOBAL_OFFSET_TABLE_ symbol is at 0x1120+0x2ee0 \u003d 0x4000.\nThat\u0027s the address of the .got.plt section. But the offset “into” the\ntable is -0x40, putting it at 0x3fd8, in .got:\n\nIdx Name          Size      VMA               LMA               File off  Algn\n 18 .got          00000030  0000000000003fd0  0000000000003fd0  00002fd0  2**3\n 19 .got.plt      00000018  0000000000004000  0000000000004000  00003000  2**3\n\nAnd, indeed, there\u0027s a dynamic relocation to setup that address:\n\nOFFSET           TYPE              VALUE\n0000000000003fd8 R_X86_64_GLOB_DAT  getpid@GLIBC_2.2.5\n\nAccessing data or BSS works the same: the address of the variable is\nstored relative to _GLOBAL_OFFSET_TABLE_.\n\nThis is a bit of a pain because we want to delocate the module into a\nsingle .text segment so that it moves through linking unaltered. If we\ntook the obvious path and built our own offset table then it would need\nto contain absolute addresses, but they are only available at runtime\nand .text segments aren\u0027t supposed to be run-time patched. (That\u0027s why\n.rela.dyn is a separate segment.) If we use a different segment then\nwe have the same problem as with the original offset table: the offset\nto the segment is unknown when compiling the module.\n\nTrying to pattern match this two-step lookup to do extensive rewriting\nseems fragile: I\u0027m sure the compilers will move things around and\ninterleave other work in time, if they don\u0027t already.\n\nSo, in order to handle movabs trying to load _GLOBAL_OFFSET_TABLE_ we\ndefine a symbol in the same segment, but outside of the hashed region of\nthe module, that contains the offset from that position to\n_GLOBAL_OFFSET_TABLE_:\n\n.boringssl_got_delta:\n    .quad _GLOBAL_OFFSET_TABLE_-.boringssl_got_delta\n\nThen a movabs of $_GLOBAL_OFFSET_TABLE_-.Lfoo turns into:\n\nmovq .boringssl_got_delta(%rip), %destreg\naddq $.boringssl_got_delta-.Lfoo, %destreg\n\nThis works because it\u0027s calculating\n_GLOBAL_OFFSET_TABLE_ - got_delta + (got_delta - .Lfoo)\n\nWhen that value is added to .Lfoo, as the original code will do, the\ncorrect address results. Also it doesn\u0027t need an extra register because\nwe know that 32-bit offsets are sufficient for offsets within the\nmodule.\n\nAs for the offsets within the offset table, we have to load them from\nlocations outside of the hashed part of the module to get the\nrelocations out of the way. Again, no extra registers are needed.\n\nChange-Id: I87b19a2f8886bd9f7ac538fd55754e526bcf3097\nReviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42324\nReviewed-by: Adam Langley \u003cagl@google.com\u003e\nCommit-Queue: Adam Langley \u003cagl@google.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "92b4c31d8bd815fa32b6356f112ebc520efad66f",
      "old_mode": 33188,
      "old_path": "util/fipstools/delocate/delocate.go",
      "new_id": "05d591193aa82044200d5c5353103f486d29cc5f",
      "new_mode": 33188,
      "new_path": "util/fipstools/delocate/delocate.go"
    },
    {
      "type": "modify",
      "old_id": "b24a47a3d41e7a41a2b1be584ed129cb7e906999",
      "old_mode": 33188,
      "old_path": "util/fipstools/delocate/delocate.peg",
      "new_id": "34dd3f6609d0fd690e81ad6be8a6c25b5d685d5f",
      "new_mode": 33188,
      "new_path": "util/fipstools/delocate/delocate.peg"
    },
    {
      "type": "modify",
      "old_id": "298f55c888a48e4ec19d5ed25721979aeb046e84",
      "old_mode": 33188,
      "old_path": "util/fipstools/delocate/delocate.peg.go",
      "new_id": "300735276505053c9a0de0771a9b52478f168305",
      "new_mode": 33188,
      "new_path": "util/fipstools/delocate/delocate.peg.go"
    },
    {
      "type": "modify",
      "old_id": "1778fa732bc1c5b217f7edb71b585eaffe6c7e19",
      "old_mode": 33188,
      "old_path": "util/fipstools/delocate/delocate_test.go",
      "new_id": "ed504a0841e3c8990ad49f873236783f5c7f240b",
      "new_mode": 33188,
      "new_path": "util/fipstools/delocate/delocate_test.go"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "57ad053edfa806162901daa3f8440fe296e382a7",
      "new_mode": 33188,
      "new_path": "util/fipstools/delocate/testdata/x86_64-LargeMemory/in.s"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "9000b010a215d4efe16e0f5bc26d23357d5e7210",
      "new_mode": 33188,
      "new_path": "util/fipstools/delocate/testdata/x86_64-LargeMemory/out.s"
    }
  ]
}
