fix cursor crash
This commit is contained in:
parent
60ff77ec1d
commit
2d12117cfb
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include "internal.hh"
|
#include "internal.hh"
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -14,57 +14,56 @@ DWARFPP_BEGIN_NAMESPACE
|
|||||||
int64_t
|
int64_t
|
||||||
cursor::sleb128()
|
cursor::sleb128()
|
||||||
{
|
{
|
||||||
// Appendix C
|
// Appendix C
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
unsigned shift = 0;
|
unsigned shift = 0;
|
||||||
while (pos < sec->end) {
|
while (pos < sec->end) {
|
||||||
uint8_t byte = *(uint8_t*)(pos++);
|
uint8_t byte = *(uint8_t *) (pos++);
|
||||||
result |= (uint64_t)(byte & 0x7f) << shift;
|
result |= (uint64_t) (byte & 0x7f) << shift;
|
||||||
shift += 7;
|
shift += 7;
|
||||||
if ((byte & 0x80) == 0) {
|
if ((byte & 0x80) == 0) {
|
||||||
if (shift < sizeof(result)*8 && (byte & 0x40))
|
if (shift < sizeof(result) * 8 && (byte & 0x40)) result |= -((uint64_t) 1 << shift);
|
||||||
result |= -((uint64_t)1 << shift);
|
return result;
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
underflow();
|
}
|
||||||
return 0;
|
underflow();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<section>
|
shared_ptr<section>
|
||||||
cursor::subsection()
|
cursor::subsection()
|
||||||
{
|
{
|
||||||
// Section 7.4
|
// Section 7.4
|
||||||
const char *begin = pos;
|
const char *begin = pos;
|
||||||
section_length length = fixed<uword>();
|
section_length length = fixed<uword>();
|
||||||
format fmt;
|
format fmt;
|
||||||
if (length < 0xfffffff0) {
|
if (length < 0xfffffff0) {
|
||||||
fmt = format::dwarf32;
|
fmt = format::dwarf32;
|
||||||
length += sizeof(uword);
|
length += sizeof(uword);
|
||||||
} else if (length == 0xffffffff) {
|
} else if (length == 0xffffffff) {
|
||||||
length = fixed<uint64_t>();
|
length = fixed<uint64_t>();
|
||||||
fmt = format::dwarf64;
|
fmt = format::dwarf64;
|
||||||
length += sizeof(uword) + sizeof(uint64_t);
|
length += sizeof(uword) + sizeof(uint64_t);
|
||||||
} else {
|
} else {
|
||||||
throw format_error("initial length has reserved value");
|
throw format_error("initial length has reserved value");
|
||||||
}
|
}
|
||||||
pos = begin + length;
|
pos = begin + length;
|
||||||
return make_shared<section>(sec->type, begin, length, sec->ord, fmt);
|
return make_shared<section>(sec->type, begin, length, sec->ord, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursor::skip_initial_length()
|
cursor::skip_initial_length()
|
||||||
{
|
{
|
||||||
switch (sec->fmt) {
|
switch (sec->fmt) {
|
||||||
case format::dwarf32:
|
case format::dwarf32:
|
||||||
pos += sizeof(uword);
|
pos += sizeof(uword);
|
||||||
break;
|
break;
|
||||||
case format::dwarf64:
|
case format::dwarf64:
|
||||||
pos += sizeof(uword) + sizeof(uint64_t);
|
pos += sizeof(uword) + sizeof(uint64_t);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw logic_error("cannot skip initial length with unknown format");
|
throw logic_error("cannot skip initial length with unknown format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -76,132 +75,128 @@ cursor::skip_unit_type()
|
|||||||
section_offset
|
section_offset
|
||||||
cursor::offset()
|
cursor::offset()
|
||||||
{
|
{
|
||||||
switch (sec->fmt) {
|
switch (sec->fmt) {
|
||||||
case format::dwarf32:
|
case format::dwarf32:
|
||||||
return fixed<uint32_t>();
|
return fixed<uint32_t>();
|
||||||
case format::dwarf64:
|
case format::dwarf64:
|
||||||
return fixed<uint64_t>();
|
return fixed<uint64_t>();
|
||||||
default:
|
default:
|
||||||
throw logic_error("cannot read offset with unknown format");
|
throw logic_error("cannot read offset with unknown format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursor::string(std::string &out)
|
cursor::string(std::string &out)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
const char *p = this->cstr(&size);
|
const char *p = this->cstr(&size);
|
||||||
out.resize(size);
|
// out.resize(size);
|
||||||
memmove(&out.front(), p, size);
|
// memmove(&out.front(), p, size);
|
||||||
|
out = std::string(p, p + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
cursor::cstr(size_t *size_out)
|
cursor::cstr(size_t *size_out)
|
||||||
{
|
{
|
||||||
// Scan string size
|
// Scan string size
|
||||||
const char *p = pos;
|
const char *p = pos;
|
||||||
while (pos < sec->end && *pos)
|
while (pos < sec->end && *pos) pos++;
|
||||||
pos++;
|
if (pos == sec->end) throw format_error("unterminated string");
|
||||||
if (pos == sec->end)
|
if (size_out) *size_out = pos - p;
|
||||||
throw format_error("unterminated string");
|
pos++;
|
||||||
if (size_out)
|
return p;
|
||||||
*size_out = pos - p;
|
|
||||||
pos++;
|
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursor::skip_form(DW_FORM form)
|
cursor::skip_form(DW_FORM form)
|
||||||
{
|
{
|
||||||
section_offset tmp;
|
section_offset tmp;
|
||||||
|
|
||||||
// Section 7.5.4
|
// Section 7.5.4
|
||||||
switch (form) {
|
switch (form) {
|
||||||
case DW_FORM::addr:
|
case DW_FORM::addr:
|
||||||
pos += sec->addr_size;
|
pos += sec->addr_size;
|
||||||
break;
|
break;
|
||||||
case DW_FORM::sec_offset:
|
case DW_FORM::sec_offset:
|
||||||
case DW_FORM::ref_addr:
|
case DW_FORM::ref_addr:
|
||||||
case DW_FORM::strp:
|
case DW_FORM::strp:
|
||||||
switch (sec->fmt) {
|
switch (sec->fmt) {
|
||||||
case format::dwarf32:
|
case format::dwarf32:
|
||||||
pos += 4;
|
pos += 4;
|
||||||
break;
|
break;
|
||||||
case format::dwarf64:
|
case format::dwarf64:
|
||||||
pos += 8;
|
pos += 8;
|
||||||
break;
|
break;
|
||||||
case format::unknown:
|
case format::unknown:
|
||||||
throw logic_error("cannot read form with unknown format");
|
throw logic_error("cannot read form with unknown format");
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// size+data forms
|
|
||||||
case DW_FORM::block1:
|
|
||||||
tmp = fixed<ubyte>();
|
|
||||||
pos += tmp;
|
|
||||||
break;
|
|
||||||
case DW_FORM::block2:
|
|
||||||
tmp = fixed<uhalf>();
|
|
||||||
pos += tmp;
|
|
||||||
break;
|
|
||||||
case DW_FORM::block4:
|
|
||||||
tmp = fixed<uword>();
|
|
||||||
pos += tmp;
|
|
||||||
break;
|
|
||||||
case DW_FORM::block:
|
|
||||||
case DW_FORM::exprloc:
|
|
||||||
tmp = uleb128();
|
|
||||||
pos += tmp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// fixed-length forms
|
|
||||||
case DW_FORM::flag_present:
|
|
||||||
break;
|
|
||||||
case DW_FORM::flag:
|
|
||||||
case DW_FORM::data1:
|
|
||||||
case DW_FORM::ref1:
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
case DW_FORM::data2:
|
|
||||||
case DW_FORM::ref2:
|
|
||||||
pos += 2;
|
|
||||||
break;
|
|
||||||
case DW_FORM::data4:
|
|
||||||
case DW_FORM::ref4:
|
|
||||||
pos += 4;
|
|
||||||
break;
|
|
||||||
case DW_FORM::data8:
|
|
||||||
case DW_FORM::ref_sig8:
|
|
||||||
pos += 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// variable-length forms
|
|
||||||
case DW_FORM::sdata:
|
|
||||||
case DW_FORM::udata:
|
|
||||||
case DW_FORM::ref_udata:
|
|
||||||
while (pos < sec->end && (*(uint8_t*)pos & 0x80))
|
|
||||||
pos++;
|
|
||||||
pos++;
|
|
||||||
break;
|
|
||||||
case DW_FORM::string:
|
|
||||||
while (pos < sec->end && *pos)
|
|
||||||
pos++;
|
|
||||||
pos++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DW_FORM::indirect:
|
|
||||||
skip_form((DW_FORM)uleb128());
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw format_error("unknown form " + to_string(form));
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// size+data forms
|
||||||
|
case DW_FORM::block1:
|
||||||
|
tmp = fixed<ubyte>();
|
||||||
|
pos += tmp;
|
||||||
|
break;
|
||||||
|
case DW_FORM::block2:
|
||||||
|
tmp = fixed<uhalf>();
|
||||||
|
pos += tmp;
|
||||||
|
break;
|
||||||
|
case DW_FORM::block4:
|
||||||
|
tmp = fixed<uword>();
|
||||||
|
pos += tmp;
|
||||||
|
break;
|
||||||
|
case DW_FORM::block:
|
||||||
|
case DW_FORM::exprloc:
|
||||||
|
tmp = uleb128();
|
||||||
|
pos += tmp;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// fixed-length forms
|
||||||
|
case DW_FORM::flag_present:
|
||||||
|
break;
|
||||||
|
case DW_FORM::flag:
|
||||||
|
case DW_FORM::data1:
|
||||||
|
case DW_FORM::ref1:
|
||||||
|
pos += 1;
|
||||||
|
break;
|
||||||
|
case DW_FORM::data2:
|
||||||
|
case DW_FORM::ref2:
|
||||||
|
pos += 2;
|
||||||
|
break;
|
||||||
|
case DW_FORM::data4:
|
||||||
|
case DW_FORM::ref4:
|
||||||
|
pos += 4;
|
||||||
|
break;
|
||||||
|
case DW_FORM::data8:
|
||||||
|
case DW_FORM::ref_sig8:
|
||||||
|
pos += 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// variable-length forms
|
||||||
|
case DW_FORM::sdata:
|
||||||
|
case DW_FORM::udata:
|
||||||
|
case DW_FORM::ref_udata:
|
||||||
|
while (pos < sec->end && (*(uint8_t *) pos & 0x80)) pos++;
|
||||||
|
pos++;
|
||||||
|
break;
|
||||||
|
case DW_FORM::string:
|
||||||
|
while (pos < sec->end && *pos) pos++;
|
||||||
|
pos++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_FORM::indirect:
|
||||||
|
skip_form((DW_FORM) uleb128());
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw format_error("unknown form " + to_string(form));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cursor::underflow()
|
cursor::underflow()
|
||||||
{
|
{
|
||||||
throw underflow_error("cannot read past end of DWARF section");
|
throw underflow_error("cannot read past end of DWARF section");
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFPP_END_NAMESPACE
|
DWARFPP_END_NAMESPACE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user