mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 17:23:06 +00:00
libdrgn: binary_buffer: add binary_buffer_next_sleb128()
Revive it from all the way back in commit 90fbec02fc
("dwarfindex:
delete unused read_sleb128() and read_strlen()") and add an _into_u64
variant. These will be used for parsing .debug_frame, .eh_frame, and
DWARF expressions.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
7eab40aaeb
commit
e5219b13e3
@ -246,6 +246,55 @@ binary_buffer_next_uleb128(struct binary_buffer *bb, uint64_t *ret)
|
||||
return binary_buffer_error_at(bb, bb->pos, "expected ULEB128 number");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a Signed Little-Endian Base 128 (SLEB128) number at the current buffer
|
||||
* position and advance the position.
|
||||
*
|
||||
* If the number does not fit in a @c int64_t, an error is returned.
|
||||
*
|
||||
* @param[out] ret Returned value.
|
||||
*/
|
||||
static inline struct drgn_error *
|
||||
binary_buffer_next_sleb128(struct binary_buffer *bb, int64_t *ret)
|
||||
{
|
||||
int shift = 0;
|
||||
int64_t value = 0;
|
||||
const char *pos = bb->pos;
|
||||
while (likely(pos < bb->end)) {
|
||||
uint8_t byte = *(uint8_t *)(pos++);
|
||||
if (unlikely(shift == 63 && byte != 0 && byte != 0x7f)) {
|
||||
return binary_buffer_error_at(bb, bb->pos,
|
||||
"SLEB128 number overflows signed 64-bit integer");
|
||||
}
|
||||
value |= (uint64_t)(byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
if (!(byte & 0x80)) {
|
||||
bb->prev = bb->pos;
|
||||
bb->pos = pos;
|
||||
if (shift < 64 && (byte & 0x40))
|
||||
value |= ~(UINT64_C(1) << shift) + 1;
|
||||
*ret = value;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return binary_buffer_error_at(bb, bb->pos, "expected SLEB128 number");
|
||||
}
|
||||
|
||||
/**
|
||||
* Like @ref binary_buffer_next_sleb128(), but return the value as a @c
|
||||
* uint64_t. Negative values are sign extended.
|
||||
*/
|
||||
static inline struct drgn_error *
|
||||
binary_buffer_next_sleb128_into_u64(struct binary_buffer *bb, uint64_t *ret)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
int64_t tmp;
|
||||
if ((err = binary_buffer_next_sleb128(bb, &tmp)))
|
||||
return err;
|
||||
*ret = tmp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Skip past a LEB128 number at the current buffer position. */
|
||||
static inline struct drgn_error *
|
||||
binary_buffer_skip_leb128(struct binary_buffer *bb)
|
||||
|
Loading…
Reference in New Issue
Block a user