blob: 3e9fe650659f1f1d39140538afb1adf066aa84e4 [file] [log] [blame]
/*
* 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;
}
c &= ~0x80;
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;
}