Due to a typo, if an unknown function was requested it was previously
ignored.
Change-Id: Id815c4b7e80d1452034b10bf9c7beb80a5ac3ed2
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43125
Reviewed-by: David Benjamin <davidben@google.com>
Sending empty spans tripped up the code because it never considered
the iovec to have been sent. Instead, filter out empty iovecs in the
first place.
Change-Id: I48ea2a887ca64c73051346f3096735c30507525a
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43124
Commit-Queue: Adam Langley <alangley@gmail.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
A direct connections to the ACVP servers may not always be available. In
some cases, NVLAP labs will interact with the servers and send JSON back
and forth as files. This change supports both dumping the capabilities
JSON (which a lab will need in order to send to the server) and
processing vectors from a file on disk.
Change-Id: Iefa0c411b9a19808b5a7eb431169068d1c2ea966
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42704
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
I tried to save space and use 32-bit GOT offsets since a GOT > 2GiB is
crazy. However, Clang's linker emits 64-bit relocations even for .long,
thus the four bytes following each offset get stomped. It mostly works
because the relocations are applied in order, thus the following
relocation gets stomped but is then processed and fixed. But there's
four bytes of stomp at the end which hits the module integrity hash,
which is fatal.
This could be fixed by adding four bytes of padding after the list of
offsets, but that's piling a hack on a hack. So this change just
switches to 64-bit offsets.
Change-Id: I227eec67c481d93a414fbed19aa99471f9df0f0e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42484
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Large memory models on x86-64 allow the code/data of a shared object /
executable to be larger than 2GiB. This is typically impossible because
x86-64 code frequently uses int32 offsets from RIP.
Consider the following program:
int getpid();
int main() {
return getpid();
}
This is turned into the following assembly under a large memory model:
.L0$pb:
leaq .L0$pb(%rip), %rax
movabsq $_GLOBAL_OFFSET_TABLE_-.L0$pb, %rcx
addq %rax, %rcx
movabsq $getpid@GOT, %rdx
xorl %eax, %eax
jmpq *(%rcx,%rdx) # TAILCALL
And, with relocations:
0: 48 8d 05 f9 ff ff ff lea -0x7(%rip),%rax # 0 <main>
7: 48 b9 00 00 00 00 00 movabs $0x0,%rcx
e: 00 00 00
9: R_X86_64_GOTPC64 _GLOBAL_OFFSET_TABLE_+0x9
11: 48 01 c1 add %rax,%rcx
14: 48 ba 00 00 00 00 00 movabs $0x0,%rdx
1b: 00 00 00
16: R_X86_64_GOT64 getpid
1e: 31 c0 xor %eax,%eax
20: ff 24 11 jmpq *(%rcx,%rdx,1)
We can see that, in the large memory model, function calls involve
loading the address of _GLOBAL_OFFSET_TABLE_ (using `movabs`, which
takes a 64-bit immediate) and then indexing into it. Both cause
relocations.
If we link the binary and disassemble we get:
0000000000001120 <main>:
1120: 48 8d 05 f9 ff ff ff lea -0x7(%rip),%rax # 1120 <main>
1127: 48 b9 e0 2e 00 00 00 movabs $0x2ee0,%rcx
112e: 00 00 00
1131: 48 01 c1 add %rax,%rcx
1134: 48 ba d8 ff ff ff ff movabs $0xffffffffffffffd8,%rdx
113b: ff ff ff
113e: 31 c0 xor %eax,%eax
1140: ff 24 11 jmpq *(%rcx,%rdx,1)
Thus the _GLOBAL_OFFSET_TABLE_ symbol is at 0x1120+0x2ee0 = 0x4000.
That's the address of the .got.plt section. But the offset “into” the
table is -0x40, putting it at 0x3fd8, in .got:
Idx Name Size VMA LMA File off Algn
18 .got 00000030 0000000000003fd0 0000000000003fd0 00002fd0 2**3
19 .got.plt 00000018 0000000000004000 0000000000004000 00003000 2**3
And, indeed, there's a dynamic relocation to setup that address:
OFFSET TYPE VALUE
0000000000003fd8 R_X86_64_GLOB_DAT getpid@GLIBC_2.2.5
Accessing data or BSS works the same: the address of the variable is
stored relative to _GLOBAL_OFFSET_TABLE_.
This is a bit of a pain because we want to delocate the module into a
single .text segment so that it moves through linking unaltered. If we
took the obvious path and built our own offset table then it would need
to contain absolute addresses, but they are only available at runtime
and .text segments aren't supposed to be run-time patched. (That's why
.rela.dyn is a separate segment.) If we use a different segment then
we have the same problem as with the original offset table: the offset
to the segment is unknown when compiling the module.
Trying to pattern match this two-step lookup to do extensive rewriting
seems fragile: I'm sure the compilers will move things around and
interleave other work in time, if they don't already.
So, in order to handle movabs trying to load _GLOBAL_OFFSET_TABLE_ we
define a symbol in the same segment, but outside of the hashed region of
the module, that contains the offset from that position to
_GLOBAL_OFFSET_TABLE_:
.boringssl_got_delta:
.quad _GLOBAL_OFFSET_TABLE_-.boringssl_got_delta
Then a movabs of $_GLOBAL_OFFSET_TABLE_-.Lfoo turns into:
movq .boringssl_got_delta(%rip), %destreg
addq $.boringssl_got_delta-.Lfoo, %destreg
This works because it's calculating
_GLOBAL_OFFSET_TABLE_ - got_delta + (got_delta - .Lfoo)
When that value is added to .Lfoo, as the original code will do, the
correct address results. Also it doesn't need an extra register because
we know that 32-bit offsets are sufficient for offsets within the
module.
As for the offsets within the offset table, we have to load them from
locations outside of the hashed part of the module to get the
relocations out of the way. Again, no extra registers are needed.
Change-Id: I87b19a2f8886bd9f7ac538fd55754e526bcf3097
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42324
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>