diff options
author | rsc <devnull@localhost> | 2004-04-19 19:29:25 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-19 19:29:25 +0000 |
commit | a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46 (patch) | |
tree | 59a0e921597e5aa53e83d487c16727a7bf01547a /src/libmach/dwarfget.c | |
parent | 0e3cc9f456ea49919459bf1164d0c8309a6134fa (diff) | |
download | plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.gz plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.bz2 plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.zip |
libmach
Diffstat (limited to 'src/libmach/dwarfget.c')
-rw-r--r-- | src/libmach/dwarfget.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/libmach/dwarfget.c b/src/libmach/dwarfget.c new file mode 100644 index 00000000..da8558c4 --- /dev/null +++ b/src/libmach/dwarfget.c @@ -0,0 +1,217 @@ +/* + * Dwarf data format parsing routines. + */ + +#include <u.h> +#include <libc.h> +#include <bio.h> +#include "elf.h" +#include "dwarf.h" + +ulong +dwarfget1(DwarfBuf *b) +{ + if(b->p==nil || b->p+1 > b->ep){ + b->p = nil; + return 0; + } + return *b->p++; +} + +int +dwarfgetn(DwarfBuf *b, uchar *a, int n) +{ + if(b->p==nil || b->p+n > b->ep){ + b->p = nil; + memset(a, 0, n); + return -1; + } + memmove(a, b->p, n); + b->p += n; + return 0; +} + +uchar* +dwarfgetnref(DwarfBuf *b, ulong n) +{ + uchar *p; + + if(b->p==nil || b->p+n > b->ep){ + b->p = nil; + return nil; + } + p = b->p; + b->p += n; + return p; +} + +char* +dwarfgetstring(DwarfBuf *b) +{ + char *s; + + if(b->p == nil) + return nil; + s = (char*)b->p; + while(b->p < b->ep && *b->p) + b->p++; + if(b->p >= b->ep){ + b->p = nil; + return nil; + } + b->p++; + return s; +} + +void +dwarfskip(DwarfBuf *b, int n) +{ + if(b->p==nil || b->p+n > b->ep) + b->p = nil; + else + b->p += n; +} + +ulong +dwarfget2(DwarfBuf *b) +{ + ulong v; + + if(b->p==nil || b->p+2 > b->ep){ + b->p = nil; + return 0; + } + v = b->d->elf->hdr.e2(b->p); + b->p += 2; + return v; +} + +ulong +dwarfget4(DwarfBuf *b) +{ + ulong v; + + if(b->p==nil || b->p+4 > b->ep){ + b->p = nil; + return 0; + } + v = b->d->elf->hdr.e4(b->p); + b->p += 4; + return v; +} + +uvlong +dwarfget8(DwarfBuf *b) +{ + uvlong v; + + if(b->p==nil || b->p+8 > b->ep){ + b->p = nil; + return 0; + } + v = b->d->elf->hdr.e8(b->p); + b->p += 8; + return v; +} + +ulong +dwarfgetaddr(DwarfBuf *b) +{ + static int nbad; + + if(b->addrsize == 0) + b->addrsize = b->d->addrsize; + + switch(b->addrsize){ + case 1: + return dwarfget1(b); + case 2: + return dwarfget2(b); + case 4: + return dwarfget4(b); + case 8: + return dwarfget8(b); + default: + if(++nbad == 1) + fprint(2, "dwarf: unexpected address size %lud in dwarfgetaddr\n", b->addrsize); + b->p = nil; + return 0; + } +} + +int n1, n2, n3, n4, n5; + +/* An inline function picks off the calls to dwarfget128 for 1-byte encodings, + * more than by far the common case (99.999% on most binaries!). */ +ulong +dwarfget128(DwarfBuf *b) +{ + static int nbad; + ulong c, d; + + if(b->p == nil) + return 0; + c = *b->p++; + if(!(c&0x80)) +{n1++; + return c; +} + d = *b->p++; + c |= (d&0x7F)<<7; + if(!(d&0x80)) +{n2++; + return c; +} + d = *b->p++; + c |= (d&0x7F)<<14; + if(!(d&0x80)) +{n3++; + return c; +} + d = *b->p++; + c |= (d&0x7F)<<21; + if(!(d&0x80)) +{n4++; + return c; +} + d = *b->p++; + c |= (d&0x7F)<<28; + if(!(d&0x80)) +{n5++; + return c; +} + while(b->p<b->ep && *b->p&0x80) + b->p++; + if(++nbad == 1) + fprint(2, "dwarf: overflow during parsing of uleb128 integer\n"); + return c; +} + +long +dwarfget128s(DwarfBuf *b) +{ + int nb, c; + ulong v; + static int nbad; + + v = 0; + nb = 0; + if(b->p==nil) + return 0; + while(b->p<b->ep){ + c = *b->p++; + v |= (c & 0x7F)<<nb; + nb += 7; + if(!(c&0x80)) + break; + } + if(v&(1<<(nb-1))) + v |= ~(((ulong)1<<nb)-1); + if(nb > 8*sizeof(ulong)){ + if(0) + if(++nbad == 1) + fprint(2, "dwarf: overflow during parsing of sleb128 integer: got %d bits\n", nb); + } + return v; +} + |