Decoding the first list of strings correctly

This commit is contained in:
Pierre Pronchery 2011-11-30 05:46:04 +00:00
parent 2513835d1b
commit 0b4301cd60

View File

@ -54,8 +54,39 @@ typedef enum _JavaCpInfoTag
typedef struct _JavaCpInfo
{
off_t offset;
uint8_t tag;
char info[0];
union {
struct {
uint16_t name;
} _class;
struct {
uint64_t value;
} _double, _long;
struct {
uint16_t _class;
uint16_t name_type;
} field, interface, method;
struct {
uint32_t value;
} _float, _integer;
struct {
uint16_t name;
uint16_t descriptor;
} name_type;
struct {
uint16_t name;
} _string;
struct {
uint16_t length;
} utf8;
} info;
} JavaCpInfo;
typedef struct _JavaHeader2
@ -78,7 +109,6 @@ typedef struct _JavaAttributeInfo
{
uint16_t name;
uint32_t length;
char info[0];
} JavaAttributeInfo;
typedef struct _JavaMethodInfo
@ -96,6 +126,7 @@ typedef struct _JavaPlugin
char * class_name;
char * super_name;
uint16_t access_flags;
JavaCpInfo * constants;
uint16_t constants_cnt;
uint16_t interfaces_cnt;
uint16_t fields_cnt;
@ -178,6 +209,7 @@ static int _exit_attribute_table(FormatPlugin * format);
static int _java_exit(FormatPlugin * format)
{
int ret = 0;
JavaPlugin * java = format->priv;
if(_exit_constant_pool(format) != 0
|| _exit_access_flags(format) != 0
@ -188,7 +220,8 @@ static int _java_exit(FormatPlugin * format)
|| _exit_method_table(format) != 0
|| _exit_attribute_table(format) != 0)
ret = 1;
free(format->priv);
free(java->constants);
free(java);
return ret;
}
@ -336,17 +369,22 @@ static int _java_decode_section(FormatPlugin * format, AsmSection * section,
ArchInstructionCall ** calls, size_t * calls_cnt)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
JavaHeader jh;
JavaHeader2 jh2;
uint16_t u16;
/* reset the status */
free(java->constants);
java->constants = NULL;
java->constants_cnt = 0;
/* read header */
if(helper->seek(helper->format, section->offset, SEEK_SET)
!= section->offset)
return -1;
if(helper->read(helper->format, &jh, sizeof(jh)) != sizeof(jh))
return -1;
/* skip constants */
/* decode constants */
jh.cp_cnt = _htob16(jh.cp_cnt);
if(jh.cp_cnt > 1 && _decode_constants(format, jh.cp_cnt) != 0)
return -1;
@ -362,7 +400,7 @@ static int _java_decode_section(FormatPlugin * format, AsmSection * section,
u16 = _htob16(u16);
if(_decode_fields(format, u16) != 0)
return -1;
/* skip methods */
/* decode methods */
if(helper->read(helper->format, &u16, sizeof(u16)) != sizeof(u16))
return -1;
u16 = _htob16(u16);
@ -394,11 +432,10 @@ static int _decode_attributes(FormatPlugin * format, uint16_t cnt,
#endif
if(calls != NULL)
{
if((offset = helper->seek(helper->format, 0, SEEK_CUR))
< 0
|| helper->decode(helper->format,
offset, jai.length, offset,
calls, calls_cnt) != 0)
offset = helper->seek(helper->format, 0, SEEK_CUR);
if(offset < 0 || helper->decode(helper->format, offset,
jai.length, offset, calls,
calls_cnt) != 0)
return -1;
}
else if(helper->seek(helper->format, jai.length, SEEK_CUR) < 0)
@ -410,86 +447,101 @@ static int _decode_attributes(FormatPlugin * format, uint16_t cnt,
static int _decode_constants(FormatPlugin * format, uint16_t cnt)
{
FormatPluginHelper * helper = format->helper;
JavaPlugin * java = format->priv;
size_t i;
JavaCpInfo jci;
JavaCpInfo * jci;
size_t size;
char buf[8];
uint16_t u16;
off_t offset;
AsmString * as;
size_t name;
JavaCpInfo * jcin;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, cnt);
#endif
if((java->constants = malloc(sizeof(*java->constants) * cnt)) == NULL)
return -error_set_code(1, "%s", strerror(errno));
java->constants_cnt = cnt;
/* zero all the constants out */
memset(java->constants, 0, sizeof(*java->constants) * cnt);
for(i = 1; i < cnt; i++)
{
if(helper->read(helper->format, &jci, sizeof(jci))
!= sizeof(jci))
jci = &java->constants[i];
if((jci->offset = helper->seek(helper->format, 0, SEEK_CUR))
< 0)
return -1;
switch(jci.tag)
if(helper->read(helper->format, &jci->tag, sizeof(jci->tag))
!= sizeof(jci->tag))
return -1;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %lu (%u)\n", __func__, i,
jci->tag);
#endif
switch(jci->tag)
{
case CONSTANT_Class:
case CONSTANT_String:
size = sizeof(jci->info._class);
if(helper->read(helper->format,
&jci->info._class,
size) != (ssize_t)size)
return -1;
jci->info._class.name = _htob16(
jci->info._class.name);
break;
case CONSTANT_Double:
case CONSTANT_Long:
size = 8;
size = sizeof(jci->info._double);
if(helper->read(helper->format,
&jci->info._double,
size) != (ssize_t)size)
return -1;
jci->info._double.value = _htob64(
jci->info._double.value);
break;
case CONSTANT_Fieldref:
case CONSTANT_Float:
case CONSTANT_Integer:
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref:
size = sizeof(jci->info.field);
if(helper->read(helper->format,
&jci->info.field,
size) != (ssize_t)size)
return -1;
jci->info.field._class = _htob16(
jci->info.field._class);
jci->info.field.name_type = _htob16(
jci->info.field.name_type);
break;
case CONSTANT_Float:
case CONSTANT_Integer:
size = sizeof(jci->info._float);
if(helper->read(helper->format,
&jci->info._float,
size) != (ssize_t)size)
return -1;
jci->info._float.value = _htob32(
jci->info._float.value);
break;
case CONSTANT_NameAndType:
size = 4;
break;
case CONSTANT_Class:
size = 2;
break;
case CONSTANT_String:
size = sizeof(u16);
if(helper->read(helper->format, &u16, size)
!= (ssize_t)size)
return -1;
u16 = _htob16(u16);
size = 0;
as = helper->get_string_by_id(helper->format,
u16 << 16);
/* set the proper string ID */
if(as != NULL && helper->set_string(
helper->format, i, NULL,
as->offset, as->size)
< 0)
return -1;
/* XXX abuse set_string() to remember string */
else if(as == NULL && helper->set_string(
helper->format,
u16 << 16, NULL, i, 0)
< 0)
size = sizeof(jci->info.name_type);
if(helper->read(helper->format,
&jci->info.name_type,
size) != (ssize_t)size)
return -1;
jci->info.name_type.name = _htob16(
jci->info.name_type.name);
jci->info.name_type.descriptor = _htob16(
jci->info.name_type.descriptor);
break;
case CONSTANT_Utf8:
size = sizeof(u16);
if(helper->read(helper->format, &u16, size)
!= (ssize_t)size)
size = sizeof(jci->info.utf8);
if(helper->read(helper->format, &jci->info.utf8,
size) != (ssize_t)size)
return -1;
u16 = _htob16(u16);
if((offset = helper->seek(helper->format, 0,
SEEK_CUR)) < 0)
return -1;
size = 0;
if(helper->seek(helper->format, u16, SEEK_CUR)
< 0)
return -1;
as = helper->get_string_by_id(helper->format,
i << 16);
/* we do not know this string yet */
if(as == NULL && helper->set_string(
helper->format, i << 16,
NULL, offset, u16) < 0)
return -1;
/* we do know this string */
else if(as != NULL && helper->set_string(
helper->format,
as->offset, NULL,
offset, u16) < 0)
jci->info.utf8.length = _htob16(
jci->info.utf8.length);
/* skip the string */
if(helper->seek(helper->format,
jci->info.utf8.length,
SEEK_CUR) < 0)
return -1;
break;
default:
@ -497,11 +549,49 @@ static int _decode_constants(FormatPlugin * format, uint16_t cnt)
helper->get_filename(
helper->format),
"Unknown constant tag",
jci.tag);
jci->tag);
}
}
/* assign all the strings */
for(i = 1; i < cnt; i++)
{
jci = &java->constants[i];
switch(jci->tag)
{
case CONSTANT_Class:
case CONSTANT_String:
if((name = jci->info._class.name) >= cnt)
continue;
if(java->constants[name].tag != CONSTANT_Utf8)
continue;
jcin = &java->constants[name];
if(helper->set_string(helper->format, i, NULL,
jcin->offset + 3,
jcin->info.utf8.length)
< 0)
return -1;
break;
case CONSTANT_Fieldref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_Methodref:
if((name = jci->info.field.name_type) >= cnt)
continue;
jcin = &java->constants[name];
if(jcin->tag != CONSTANT_NameAndType)
continue;
if((name = jcin->info.name_type.descriptor)
>= cnt)
continue;
jcin = &java->constants[name];
if(jcin->tag != CONSTANT_Utf8)
continue;
if(helper->set_string(helper->format, i, NULL,
jcin->offset + 3,
jcin->info.utf8.length)
< 0)
return -1;
break;
}
if(size != 0 && helper->read(helper->format, buf, size)
!= (ssize_t)size)
return -1;
}
return 0;
}