Add elf_read_{,next_}uleb128
diff --git a/ltrace-elf.c b/ltrace-elf.c
index b2e6e07..b045d64 100644
--- a/ltrace-elf.c
+++ b/ltrace-elf.c
@@ -263,6 +263,38 @@
#undef DEF_READER
int
+elf_read_next_uleb128(Elf_Data *data, GElf_Xword *offset, uint64_t *retp)
+{
+ uint64_t result = 0;
+ int shift = 0;
+ int size = 8 * sizeof result;
+
+ while (1) {
+ uint8_t byte;
+ if (elf_read_next_u8(data, offset, &byte) < 0)
+ return -1;
+
+ uint8_t payload = byte & 0x7f;
+ result |= (uint64_t)payload << shift;
+ shift += 7;
+ if (shift > size && byte != 0x1)
+ return -1;
+ if ((byte & 0x80) == 0)
+ break;
+ }
+
+ if (retp != NULL)
+ *retp = result;
+ return 0;
+}
+
+int
+elf_read_uleb128(Elf_Data *data, GElf_Xword offset, uint64_t *retp)
+{
+ return elf_read_next_uleb128(data, &offset, retp);
+}
+
+int
open_elf(struct ltelf *lte, const char *filename)
{
lte->fd = open(filename, O_RDONLY);
diff --git a/ltrace-elf.h b/ltrace-elf.h
index a520e63..af97b0a 100644
--- a/ltrace-elf.h
+++ b/ltrace-elf.h
@@ -116,12 +116,17 @@
int elf_read_u32(Elf_Data *data, GElf_Xword offset, uint32_t *retp);
int elf_read_u64(Elf_Data *data, GElf_Xword offset, uint64_t *retp);
+/* Read at most 64-bit quantity recorded in an ULEB128 variable-length
+ * encoding. */
+int elf_read_uleb128(Elf_Data *data, GElf_Xword offset, uint64_t *retp);
+
/* These are same as above, but update *OFFSET with the width
* of read datum. */
int elf_read_next_u8(Elf_Data *data, GElf_Xword *offset, uint8_t *retp);
int elf_read_next_u16(Elf_Data *data, GElf_Xword *offset, uint16_t *retp);
int elf_read_next_u32(Elf_Data *data, GElf_Xword *offset, uint32_t *retp);
int elf_read_next_u64(Elf_Data *data, GElf_Xword *offset, uint64_t *retp);
+int elf_read_next_uleb128(Elf_Data *data, GElf_Xword *offset, uint64_t *retp);
#if __WORDSIZE == 32
#define PRI_ELF_ADDR PRIx32