I am trying to create a linked list that stores return instructions while parsing an assembly code file. As an explanation for the code, when encountering a call instruction the address of the next instruction is to be saved. When encountering a return instruction, the linked list is supposed to be traversed until it reaches a point when the next node is NULL. For some reason the code is not saving the return addresses. Might it have something to do with the recursion?
//function to create a node in linked list
struct ret_addr *return_address(cs_insn *insn, struct ret_addr *r) {
struct ret_addr *ret = malloc(sizeof(*ret));
ret->address = insn->address + insn->size;
ret->nxt_ret_addr = r;
return ret;
}
//retrieve the data from the last node of the linked list
int return_val(struct ret_addr *r) {
if(r == NULL)
return 0;
while(r->nxt_ret_addr != NULL) {
r = r->nxt_ret_addr;
return r->address;
}
}
//parse assembly code
struct bb_data *disassemble_function_cfg(int startAddr, unsigned char *bytes, int end_section) {
csh handle;
cs_insn *insn;
cs_detail *detail;
size_t count;
int stop_disasm = 0;
struct ret_addr *r_data = malloc(sizeof(*r_data));
count = cs_disasm(handle, bytes, end_section, startAddr, 1, &insn);
detail = insn->detail;
for(int n = 0; n < detail->groups_count; n++) {
if(detail->groups[n] == X86_GRP_CALL) {
stop_disasm = 1;
r_data = return_address(insn, r_data);
}
else if(detail->groups[n] == X86_GRP_RET) {
stop_disasm = 1;
start_edge = return_val(r_data);
}
if(!stop_disasm)
disassemble_function_cfg(insn->address + insn->size, bytes + insn->size, end_section);
else
return edges;
}
During an inital call instruction the return value is saved (checked by printing it out), but when reaching a return instruction the linked list is suddenly empty. My idea is that this is caused by the constant calls to malloc, but am unsure if that is a correct assumption.
The problem is in the return_val function : it does not modify the r_datavalue from the caller function disassemble_function_cfg.
There's also one little thing I assumed : since it is a call/return implementation, the linked list should behave as LIFO (last in first out). The return_address function fills the linked list by inserting in the head, so the return_val function should remove address from the head first : there's no need to read the list until reaching NULL.
Try this code :
//retrieve the data from the last node of the linked list
int return_val(struct ret_addr **r) {
int ret_val;
if (*r == NULL)
return 0;
ret_val = (*r)->address;
*r = (*r)->nxt_ret_addr;
return ret_val;
}
In the caller function :
else if(detail->groups[n] == X86_GRP_RET) {
stop_disasm = 1;
start_edge = return_val(&r_data); // address of r_data, so it can be modified
}
Related
Im trying to create a recursive function that creates an array of post order integers from a given tree. This is the code:
//structure
typedef struct node
{
// Each node holds a single integer.
int data;
// Pointers to the node's left and right children.
struct node *left, *right;
} node;
// preorder_recursive is same as postorder_recursive(), except
// array[i] comes before the recursive calls
int *postorder_recursive(node *root)
{
int *array = malloc(sizeof(node) * node_count(root)); // node_count(root) counts nodes in binary tree
int i = 0;
if (root == NULL)
return 0;
while (root != NULL)
{
postorder_recursive(root->left);
postorder_recursive(root->right);
array[i] = root->data;
i++;
}
return array;
}
// returns 1 if pre order = post order, returns 0 otherwise
int compare(node *a, node *b)
{
int i = 0;
int *preArray, *postArray;
if (node_count(a) != node_count(b))
return 0;
preArray = preorder_recursive(a);
postArray = postorder_recursive(b);
for (i = 0; i < node_count(a); i++)
{
if (preArray[i] != postArray[i])
return 0;
}
free(preArray);
free(postArray);
return 1;
}
I am not entirely sure if the error is in this function, but if it is, it's probably due to the while loop. Any help would be great.
Edit: Ive included a lot more code. The purpose of this is to compare an array of post order to an array of pre-order.
Your function postorder_recursive() is creating a new array every time it is called. Furthermore, while(root != NULL) will loop forever for non-empty trees, if it weren't for the fact that it writes past the end of array and cause a segmentation fault at some point.
The solution is to split the function into one that creates the array, and then another function that recursively fills in the array, like so:
static size_t postorder_recursive(const node *root, int *array, size_t index) {
if (root == NULL)
return index;
index = postorder_recursive(root->left, array, index);
index = postorder_recursive(root->right, array, index);
array[index++] = root->data;
return index;
}
int *postorder_to_array(const node *root)
{
int *array = malloc(sizeof(node) * node_count(root));
postorder_recursive(root, array, 0);
return array;
}
I am trying to implement a linked list that would store a memory address when encountering call/return assembly instructions. This works recursively by parsing each line of the assembly and only breaking out of the function when encountering either a call or return instruction. So far this works for call instructions, meaning that the return address is saved a node in a linked list, but when trying to retrieve this value during a return instruction the data has gone missing (meaning that the linked list is now empty). Here is what I am working with:
struct ret_addr {
int address;
struct ret_addr *nxt;
};
struct ret_addr *ret_data(cs_insn *insn, struct ret_addr **head) {
struct ret_addr *r = malloc(sizeof(*r));
r->address = insn->address + insn->size;
r->nxt = (*head);
(*head) = r;
return r;
}
struct bb_data *disassemble_function_cfg(int startAddr, unsigned char *bytes, int end_section) {
csh handle;
cs_insn *insn;
cs_detail *detail;
cs_x86 *x86;
size_t count;
int stop_disasm = 0;
struct bb_data *edges = NULL;
struct ret_addr *ret_edge = NULL;
count = cs_disasm(handle, bytes, end_section, startAddr, 1, &insn);
detail = insn->detail;
for(int n = 0; n < detail->groups_count; n++) {
//break when encountering a call instruction
if(detail->groups[n] == X86_GRP_CALL) {
stop_disasm = 1;
vector_new(edges);
edges = call_insn(handle, x86, insn, vector_back(edges));
ret_edge = ret_data(insn, &ret_edge);
}
//break when encountering a return instruction
else if(detail->groups[n] == X86_GRP_RET) {
stop_disasm = 1;
vector_new(edges);
edges = ret_insn(insn, edges, &ret_edge);
}
}
if(!stop_disasm) {
disassemble_function_cfg(insn->address + insn->size, bytes + insn->size, end_section);
}
else {
return edges;
}
}
You don't preserve your list between recursive calls. What you might want to do:
struct bb_data *disassemble_function_cfg(struct ret_addr **ret_edge, int startAddr, unsigned char *bytes, int end_section)
{
...
if(*ret_edge == NULL) *ret_edge = ret_data(insn, ret_edge);
...
}
I'm currently dealing with a generic Tree with this structure:
typedef struct NODE {
//node's keys
unsigned short *transboard;
int depth;
unsigned int i;
unsigned int j;
int player;
int value;
struct NODE *leftchild; //points to the first child from the left
struct NODE *rightbrothers; //linked list of brothers from the current node
}NODE;
static NODE *GameTree = NULL;
While the function that allocates the different nodes is (don't bother too much at the keys' values, basically allocates the children-nodes. If there aren't any the new child goes to leftchild, otherwise it goes at the end of the list "node->leftchild->rightbrothers"):
static int AllocateChildren(NODE **T, int depth, unsigned int i, unsigned int j, int player, unsigned short *transboard) {
NODE *tmp = NULL;
if ((*T)->leftchild == NULL) {
if( (tmp = (NODE*)malloc(sizeof(NODE)) )== NULL) return 0;
else {
tmp->i = i;
tmp->j = j;
tmp->depth = depth;
(player == MAX ) ? (tmp->value = 2 ): (tmp->value = -2);
tmp->player = player;
tmp->transboard = transboard;
tmp->leftchild = NULL;
tmp->rightbrothers = NULL;
(*T)->leftchild = tmp;
}
}
else {
NODE *scorri = (*T)->leftchild;
while (scorri->rightbrothers != NULL)
scorri = scorri->rightbrothers;
if( ( tmp = (NODE*)malloc(sizeof(NODE)) )== NULL) return 0;
else {
tmp->i = i;
tmp->j = j;
tmp->depth = depth;
(player == MAX) ? (tmp->value = 2) : (tmp->value = -2);
tmp->player = player;
tmp->transboard = transboard;
tmp->leftchild = NULL;
tmp->rightbrothers = NULL;
}
scorri->rightbrothers = tmp;
}
return 1;
}
I need to come up with a function, possibly recursive, that deallocates the whole tree, so far I've come up with this:
void DeleteTree(NODE **T) {
if((*T) != NULL) {
NODE *tmp;
for(tmp = (*T)->children; tmp->brother != NULL; tmp = tmp->brother) {
DeleteTree(&tmp);
}
free(*T);
}
}
But it doesn't seem working, it doesn't even deallocate a single node of memory.
Any ideas of where I am being wrong or how can it be implemented?
P.s. I've gotten the idea of the recursive function from this pseudocode from my teacher. However I'm not sure I've translated it correctly in C with my kind of Tree.
Pseudocode:
1: function DeleteTree(T)
2: if T != NULL then
3: for c ∈ Children(T) do
4: DeleteTree(c)
5: end for
6: Delete(T)
7: end if
8: end function
One thing I like doing if I'm allocating lots of tree nodes, that are going to go away at the same time, is to allocate them in 'batches'. I malloc then as an array of nodes and dole them out from a special nodealloc function after saving a pointer to the array (in a function like below). To drop the tree I just make sure I'm not keeping any references and then call the free routine (also like below).
This can also reduce the amount of RAM you allocate if you're lucky (or very smart) with your initial malloc or can trust realloc not to move the block when you shrink it.
struct freecell { struct freecell * next; void * memp; } * saved_pointers = 0;
static void
save_ptr_for_free(void * memp)
{
struct freecell * n = malloc(sizeof*n);
if (!n) {perror("malloc"); return; }
n->next = saved_pointers;
n->memp = memp;
saved_pointers = n;
}
static void
free_saved_memory(void)
{
while(saved_pointers) {
struct freecell * n = saved_pointers;
saved_pointers = saved_pointers->next;
free(n->memp);
free(n);
}
}
I've just realized my BIG mistake in the code and I'll just answer myself since no one had found the answer.
The error lies in this piece of code:
for(tmp = (*T)->children; tmp->brother != NULL; tmp = tmp->brother) {
DeleteTree(&tmp);
}
First of all Ami Tavory was right about the for condition, i need to continue as long as tmp != NULL
Basically it won't just work because after the DeleteTree(&tmp), I can no longer access the memory in tmp because it's obviously deleted, so after the first cycle of for ends I can't do tmp = tmp->rightbrother to move on the next node to delete because tmp->rightbrother no longer exists as I just deleted it.
In order to fix it I just needed to save the tmp->brother somewhere else:
void DeleteTree(NODE **T) {
if((*T) != NULL) {
NODE *tmp, *deletenode, *nextbrother;
for(tmp = (*T)->children; tmp != NULL; tmp = nextbrother) {
nextbrother = tmp->rightbrother;
DeleteTree(&tmp);
}
canc = (*T);
free(*T);
(*T) = NULL;
}
}
Just for the sake of completeness I want to add my version of DeleteTree
void DeleteTree(NODE *T) {
if(T != NULL) {
DeleteTree(T->rightbrothers);
DeleteTree(T->leftchild);
free(T);
}
}
I think it is much less obscure and much easier to read. Basically it solves the issue in DeleteTree but through eliminating the loop.
Since we free the nodes recursively we might as well do the whole process recursively.
I am new to C and am having issues implementing an insert function for my HashTable.
Here are my structs:
typedef struct HashTableNode {
char *url; // url previously seen
struct HashTableNode *next; // pointer to next node
} HashTableNode;
typedef struct HashTable {
HashTableNode *table[MAX_HASH_SLOT]; // actual hashtable
} HashTable;
Here is how I init the table:
HashTable *initTable(){
HashTable* d = (HashTable*)malloc(sizeof(HashTable));
int i;
for (i = 0; i < MAX_HASH_SLOT; i++) {
d->table[i] = NULL;
}
return d;
}
Here is my insert function:
int HashTableInsert(HashTable *table, char *url){
long int hashindex = JenkinsHash(url, MAX_HASH_SLOT);
int uniqueBool = 2; // 0 for true, 1 for false, 2 for init
HashTableNode* theNode = (HashTableNode*)malloc(sizeof(HashTableNode));
theNode->url = url;
if (table->table[hashindex] != NULL) { // if we have a collision
HashTableNode* currentNode = (HashTableNode*)malloc(sizeof(HashTableNode));
currentNode = table->table[hashindex]->next; // the next node in the list
if (currentNode == NULL) { // only one node currently in list
if (strcmp(table->table[hashindex]->url, theNode->url) != 0) { // unique node
table->table[hashindex]->next = theNode;
return 0;
}
else{
printf("Repeated Node\n");
return 1;
}
}
else { // multiple nodes in this slot
printf("There was more than one element in this slot to start with. \n");
while (currentNode != NULL)
{
// SEGFAULT when accessing currentNode->url HERE
if (strcmp(currentNode->url, table->table[hashindex]->url) == 0 ){ // same URL
uniqueBool = 1;
}
else{
uniqueBool = 0;
}
currentNode = currentNode->next;
}
}
if (uniqueBool == 0) {
printf("Unique URL\n");
theNode->next = table->table[hashindex]->next; // splice current node in
table->table[hashindex]->next = theNode; // needs to be a node for each slot
return 0;
}
}
else{
printf("simple placement into an empty slot\n");
table->table[hashindex] = theNode;
}
return 0;
}
I get SegFault every time I try to access currentNode->url (the next node in the linked list of a given slot), which SHOULD have a string in it if the node itself is not NULL.
I know this code is a little dicey, so thank you in advance to anyone up for the challenge.
Chip
UPDATE:
this is the function that calls all ht functions. Through my testing on regular strings in main() of hash table.c, I have concluded that the segfault is due to something here:
void crawlPage(WebPage * page){
char * new_url = NULL;
int pos= 0;
pos = GetNextURL(page->html, pos, URL_PREFIX, &new_url);
while (pos != -1){
if (HashTableLookup(URLsVisited, new_url) == 1){ // url not in table
printf("url is not in table......\n");
hti(URLsVisited, new_url);
WebPage * newPage = (WebPage*) calloc(1, sizeof(WebPage));
newPage->url = new_url;
printf("Adding to LIST...\n");
add(&URLList, newPage); // added & to it.. no seg fault
}
else{
printf("skipping url cuz it is already in table\n");
}
new_url = NULL;
pos = GetNextURL(page->html, pos, URL_PREFIX, &new_url);
}
printf("freeing\n");
free(new_url); // cleanup
free(page); // free current page
}
Your hash table insertion logic violates some rather fundamental rules.
Allocating a new node before determining you actually need one.
Blatant memory leak in your currentNode allocation
Suspicious ownership semantics of the url pointer.
Beyond that, this algorithm is being made way too complicated for what it really should be.
Compute the hash index via hash-value modulo the table size.
Start at the table slot of the hash index, walking node pointers until one of two things happens:
You discover the node is already present
You reach the end of the collision chain.
Only in #2 above do you actually allocate a collision node and chain it to your existing collision list. Most of this is trivial when employing a pointer-to-pointer approach, which I demonstrate below:
int HashTableInsert(HashTable *table, const char *url)
{
// find collision list starting point
long int hashindex = JenkinsHash(url, MAX_HASH_SLOT);
HashTableNode **pp = table->table+hashindex;
// walk the collision list looking for a match
while (*pp && strcmp(url, (*pp)->url))
pp = &(*pp)->next;
if (!*pp)
{
// no matching node found. insert a new one.
HashTableNode *pNew = malloc(sizeof *pNew);
pNew->url = strdup(url);
pNew->next = NULL;
*pp = pNew;
}
else
{ // url already in the table
printf("url \"%s\" already present\n", url);
return 1;
}
return 0;
}
That really is all there is to it.
The url ownership issue I mentioned earlier is addressed above via string duplication using strdup(). Although not a standard library function, it is POSIX compliant and every non-neanderthal half-baked implementation I've seen in the last two decades provides it. If yours doesn't (a) I'd like to know what you're using, and (b) its trivial to implement with strlen and malloc. Regardless, when the nodes are being released during value-removal or table wiping, be sure and free a node's url before free-ing the node itself.
Best of luck.
I am goofing around with pointers and structures. I want to achieve the following:
(1) define a linked list with a structure (numberRecord)
(2) write a function that fills a linked list with some sample records by going thourgh a loop (fillList)
(3) count the number of elements in the linked list
(4) print the number of elements
I am now so far that the fillList function works well, but I do not succeed in handing over the filled linked list to a pointer in the main(). In the code below, the printList function only displays the single record that was added in main() instead of displaying the list that was created in the function fillList.
#include <stdio.h>
#include <stdlib.h>
typedef struct numberRecord numberRecord;
//linked list
struct numberRecord {
int number;
struct numberRecord *next;
};
//count #records in linked list
int countList(struct numberRecord *record) {
struct numberRecord *index = record;
int i = 0;
if (record == NULL)
return i;
while (index->next != NULL) {
++i;
index = index->next;
}
return i + 1;
}
//print linked list
void printList (struct numberRecord *record) {
struct numberRecord *index = record;
if (index == NULL)
printf("List is empty \n");
while (index != NULL) {
printf("%i \n", index->number);
index = index->next;
}
}
//fill the linked list with some sample records
void fillList(numberRecord *record) {
numberRecord *first, *prev, *new, *buffer;
//as soon as you add more records you get an memory error, static construction
new = (numberRecord *)malloc(100 * sizeof(numberRecord));
new->number = 0;
new->next = NULL;
first = new;
prev = new;
buffer = new;
int i;
for (i = 1; i < 11; i++) {
new++;
new->number = i;
new->next = NULL;
prev->next = new;
prev = prev->next;
}
record = first;
}
int main(void) {
numberRecord *list;
list = malloc(sizeof(numberRecord));
list->number = 1;
list->next = NULL;
fillList(list);
printf("ListCount: %i \n", countList(list));
printList(list);
return 0;
}
SOLUTION
Do read the posts below, they indicated this solution and contain some very insightful remarks about pointers. Below the adapted code that works:
#include <stdio.h>
#include <stdlib.h>
typedef struct numberRecord numberRecord;
//linked list
struct numberRecord {
int number;
struct numberRecord *next;
};
//count #records in linked list
int countList(struct numberRecord *record) {
struct numberRecord *index = record;
int i = 0;
if (record == NULL)
return i;
while (index->next != NULL) {
++i;
index = index->next;
}
return i + 1;
}
//print linked list
void printList (struct numberRecord *record) {
struct numberRecord *index = record;
if (index == NULL)
printf("List is empty \n");
while (index != NULL) {
printf("%i \n", index->number);
index = index->next;
}
}
//fill the linked list with some sample records
numberRecord *fillList() {
numberRecord *firstRec, *prevRec, *newRec;
int i;
for (i = 1; i < 11; i++) {
newRec = malloc(sizeof(numberRecord));
newRec->number = i;
newRec->next = NULL;
//initialize firstRec and prevRec with newRec, firstRec remains head
if (i == 1) {
firstRec = newRec;
prevRec = newRec;
}
prevRec->next = newRec;
prevRec = prevRec->next;
}
return firstRec;
}
int main(void) {
numberRecord *list;
list = fillList();
printf("ListCount: %i \n", countList(list));
printList(list);
return 0;
}
This statement in fillList
record = first;
has no effect on the list variable in main. Pointers are passed by value (like everything else) in C. If you want to update the list variable in main, you'll either have to pass a pointer to it (&list) and modify fillList accordingly, or return a numberRecord* from fillList. (I'd actually go with that second option.)
Here's a (bad) illustration:
When main calls fillList, at the starting point of that function, the pointers are like this:
main memory fillList
list ----> 0x01234 <---- record
A bit later in fillList, you allocate some storage for new (that's actually a bad name, it conflicts with an operator in C++, will get people confused)
main memory fillList
list ----> 0x01234 <---- record
0x03123 <---- new
At the last line of fillList you're left with:
main memory fillList
list ----> 0x01234 ,-- record
0x03123 <---- new
record and list are not the same variable. They start out with the same value, but changing record will not change list. The fact that they are both pointers doesn't make them any different from say ints in this respect.
You can change the thing pointed to by list in fillList, but you can't change what list points to (with your version of the code).
The easiest way for you to get around that is to change fillList like this:
numberRecord *fillList() {
....
return new;
}
And in main, don't allocate list directly, just call fillList() to initialize it.