-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpftrace: Fix bitfield access for Big endian #1628
Conversation
src/ast/codegen_llvm.cpp
Outdated
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | ||
rshiftbits = field.bitfield.access_rshift; | ||
#else | ||
// Number of bytes to shift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Number of bytes to shift | |
// Number of bits to shift |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but i'd leave the comment out, or explain the logic behind how this shifting works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, Sure. I will explain with an example in the commit message then. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in the commit message. Thanks
Algorithm explaination with example: 1. struct Foo { unsigned int a:4, b:8, c:3, d:1, e:16; }; 2. Let's say a = 1, b = 2, c = 5, d = 0, c = 65535 3. Interpretation in Big endian: 0001 0000 0010 101 0 1111 1111 1111 1111 ---- --------- --- - ------------------- a b c d e In clang_parser, we calculate number of bits to shift within the number of bytes to be read. For $foo->b, in clang_parser.cpp: - bitfield.read_bytes = 2 bytes [ 2 bytes should be read inorder to retrieve the value associated with foo->b ] - bitfield_offset = 4 [ starts from offset 4 ] - bitfield_bitwidth = 8 [ length of the foo->b ] bitfield.access_rshift -> calculate number of bits to shift within bitfield.read_bytes read boundary. Before that, Lets see the final output that is desired from codegen 0000 0000 0000 0000 0000 0001 0000 0010 AND FFFF FFFF --------- 0000 0010 - Set field.bitfield.mask = FFFF FFFF - Shift 4 bits in the 2 read bytes (16 bits), This is calculated as: - bitfield.access_rshift = (bitfield.read_bytes * 8 - bitfield_offset - bitfield_bitwidth); - bitfield.access_rshift = (2*8 - (4+8)) = 4 bits. 4.Consider codegen_llvm.cpp, bitfield usecase: bpftrace -v -e 'struct Foo { unsigned int a:4, b:8, c:3, d:1, e: 16; } uprobe:./testprogs/bitfield_test:func{ $foo = (struct Foo *)arg0; printf("%d\n", $foo-> b); exit()}' Attaching 1 probe... Program ID: 54 The verifier log: 0: (bf) r6 = r1 1: (79) r3 = *(u64 *)(r6 +40) 2: (b7) r1 = 0 3: (7b) *(u64 *)(r10 -24) = r1 last_idx 3 first_idx 0 regs=2 stack=0 before 2: (b7) r1 = 0 4: (63) *(u32 *)(r10 -4) = r1 <---- dst size, field.type.GetSize() 5: (bf) r1 = r10 6: (07) r1 += -4 7: (b7) r2 = 2 8: (85) call bpf_probe_read_user#112 last_idx 8 first_idx 0 regs=4 stack=0 before 7: (b7) r2 = 2 9: (61) r1 = *(u32 *)(r10 -4) - field.offset is 0, start reading from offset 0 for $foo->b. For foo->c, field.offset is 1 [ start reading from byte 1 ] - field.type.GetSize() is the destination size. [ 32 bit for int bitfield, for short 16 bit ] - Perform the CreateProbeRead starting from offset 0, read 2 bytes 0001 0000 0010 1010 0000 0000 0000 0000 ---- |-------| |--| < zero > a b - Now calculate number of bytes to right shift (should be 2 bytes) - rshiftbits = (field.type.GetSize() - field.bitfield.read_bytes) * 8; - rshiftbits = (4-2)*8 = 16 - 0000 0000 0000 0000 | 0001 0000 0010 1010 | --------- b - Now rightshift 4 bits within this 2 bytes. [ This 4 bits value is already calculated in clang_parser.cpp ] - rshiftbits += field.bitfield.access_rshift; - 0000 0000 0000 0000 0000 0001 0000 0010 - Finally mask this value with 0xFFFF FFFF (field.bitfield.mask) - 0000 0000 0000 0000 0000 0000 0010 -> which is 2. Signed-off-by: Sumanth Korikkar <[email protected]>
Signed-off-by: Sumanth Korikkar <[email protected]>
053a6fb
to
0340026
Compare
* 'master' of github.com:iovisor/bpftrace: types: (hacky) fix sizedtype memleak with shared_ptr bpftrace: Fix bitfield access for Big endian (bpftrace#1628)
This resolves bitfield access for big endian systems.
Also added testcases to cover few more cases.
Thanks
Checklist
docs/reference_guide.md
CHANGELOG.md