/* * Dwarf data format parsing routines. */ #include #include #include #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->pep && *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->pep){ c = *b->p++; v |= (c & 0x7F)< 8*sizeof(ulong)){ if(0) if(++nbad == 1) fprint(2, "dwarf: overflow during parsing of sleb128 integer: got %d bits\n", nb); } return v; }