I am trying to debug native C code for an Android application, where I am getting the following segfault:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1640]
0x8463022c in new_field_info (tree=0x7c1a98, hfinfo=0x865b6344, tvb=0xa65100, start=8, item_length=2) at proto.c:3491
3491 proto.c: No such file or directory.
in proto.c
(gdb) bt
#0 0x8463022c in new_field_info (tree=0x7c1a98, hfinfo=0x865b6344, tvb=0xa65100, start=8, item_length=2) at proto.c:3491
#1 0x846303dc in alloc_field_info (tree=0x7c1a98, hfindex=30607, tvb=0xa65100, start=8, length=0xbeb703b0) at proto.c:3519
#2 0x8462fcdc in proto_tree_add_pi (tree=0x7c1a98, hfindex=30607, tvb=0xa65100, start=8, length=0xbeb703b0, pfi=0xbeb70398) at proto.c:3328
The relevant code is:
static field_info *
new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
const gint start, const gint item_length)
{
field_info *fi;
FIELD_INFO_NEW(fi);
if(fi == NULL)
throwDissectorException("proto.c", 3483, "fi==NULL");
fi->hfinfo = hfinfo; // THIS IS LINE 3491 <----- SEGFAULT
fi->start = start;
fi->start+=(tvb)?TVB_RAW_OFFSET(tvb):0;
fi->length = item_length;
fi->tree_type = -1;
fi->flags = 0;
...
return fi;
}
I verify that fi is not NULL, as shown, throwing an Exception which is caught by my Java application. I never see an Exception thrown (which I have tested). So, fi is guaranteed to be non-NULL.
If that is the case, then how can this segfault?
EDIT: FIELD_INFO_NEW() is in fact a macro. This is code that belongs to Wireshark that I am trying to debug, since it keeps crashing my application.
#define FIELD_INFO_NEW(fi) \
SLAB_ALLOC(fi, field_info)
/* we never free any memory we have allocated, when it is returned to us
we just store it in the free list until (hopefully) it gets used again
*/
#define SLAB_ALLOC(item, type) \
if(!type ## _free_list){ \
int i; \
union type ## slab_item *tmp; \
tmp=g_malloc(NITEMS_PER_SLAB*sizeof(*tmp)); \
for(i=0;i<NITEMS_PER_SLAB;i++){ \
tmp[i].next_free = type ## _free_list; \
type ## _free_list = &tmp[i]; \
} \
} \
item = &(type ## _free_list->slab_item); \
type ## _free_list = type ## _free_list->next_free;
I don’t think I should be checking if fi->hfinfo is valid, right? Because, I think from this code SLAB_ALLOC will allocate (or pull in already existing memory) the proper size for fi. Because, hfinfo is a pointer. Therefore, I’m just trying to give that pointer a value, and that assignment is causing the crash:
/** Contains the field information for the proto_item. */
typedef struct field_info {
header_field_info *hfinfo; /**< pointer to registered field information */
gint start; /**< current start of data in field_info.ds_tvb */
gint length; /**< current data length of item in field_info.ds_tvb */
gint appendix_start; /**< start of appendix data */
gint appendix_length; /**< length of appendix data */
gint tree_type; /**< one of ETT_ or -1 */
item_label_t *rep; /**< string for GUI tree */
guint32 flags; /**< bitfield like FI_GENERATED, ... */
tvbuff_t *ds_tvb; /**< data source tvbuff */
fvalue_t value;
} field_info;
Null pointer is only a particular case of segfault.
segfaultmeans you are trying to access to a portion (segment) of memory that is not allocated to your process.So what exactly FIELD_INFO_NEW(fi) is doing ? Does it allocate memory via malloc for example ?
I got the impression that fi is not correctly initialized. So basically you are trying to assign data at a random address that happens to be forbidden.
(And you are lucky it throws a segfault, because if you were by chance writing to an allowed memory area it would be harder to find out the cause of memory corruption that could trigger strange side effect much later in your code execution.)