From 3f76635057242e6d9f4645e7c63707467136cc23 Mon Sep 17 00:00:00 2001 From: Hizenberg Date: Wed, 15 May 2024 23:38:13 +0530 Subject: [PATCH] Implementation finished --- CMakeLists.txt | 2 +- app/app.c | 37 ++--- include/mld.h | 32 +++- src/mld.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 469 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 965dd27..4a7d038 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 17) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) -set(MLD_LIB libmld) +set(MLD_LIB mld) set(TEST_APP test_app) set(HEADER_DIR ${CMAKE_SOURCE_DIR}/include) diff --git a/app/app.c b/app/app.c index 94f2d3f..3955a0b 100644 --- a/app/app.c +++ b/app/app.c @@ -29,7 +29,7 @@ main(int argc, char** argv) { /*Step 1 : Initialize a new structure database */ struct_db_t* struct_db = calloc(1, sizeof(struct_db_t)); - //mld_init_primitive_data_types_support(struct_db); + mld_init_primitive_data_types_support(struct_db); /*Step 2 : Create structure record for structure emp_t*/ static field_info_t emp_fields[] = { @@ -57,29 +57,30 @@ main(int argc, char** argv) { - ///*Working with object database*/ - ///*Step 1 : Initialize a new Object database */ - //object_db_t* object_db = calloc(1, sizeof(object_db_t)); - //object_db->struct_db = struct_db; + /*Working with object database*/ + /*Step 1 : Initialize a new Object database */ + object_db_t* object_db = calloc(1, sizeof(object_db_t)); + object_db->struct_db = struct_db; - ///*Step 2 : Create some sample objects, equivalent to standard - // * calloc(1, sizeof(student_t))*/ - //student_t* abhishek = xcalloc(object_db, "student_t", 1); - //mld_set_dynamic_object_as_root(object_db, abhishek); + /*Step 2 : Create some sample objects, equivalent to standard + * calloc(1, sizeof(student_t))*/ + student_t* abhishek = xcalloc(object_db, "student_t", 1); + mld_set_dynamic_object_as_root(object_db, abhishek); - //student_t* shivani = xcalloc(object_db, "student_t", 1); - //strncpy(shivani->stud_name, "shivani", strlen("shivani")); - ////abhishek->best_colleage = shivani; + student_t* shivani = xcalloc(object_db, "student_t", 1); + strncpy(shivani->stud_name, "shivani", strlen("shivani")); + //abhishek->best_colleage = shivani; - //emp_t* joseph = xcalloc(object_db, "emp_t", 2); + emp_t* joseph = xcalloc(object_db, "emp_t", 2); //mld_set_dynamic_object_as_root(object_db, joseph); - //joseph->p = xcalloc(object_db, "int", 1); + joseph->p = xcalloc(object_db, "int", 1); + joseph->p = NULL; - //print_object_db(object_db); + print_object_db(object_db); - //run_mld_algorithm(object_db); - //printf("Leaked Objects : \n"); - //report_leaked_objects(object_db); + run_mld_algorithm(object_db); + printf("Leaked Objects : \n"); + report_leaked_objects(object_db); return 0; } \ No newline at end of file diff --git a/include/mld.h b/include/mld.h index dcf1cd4..fcd6e53 100644 --- a/include/mld.h +++ b/include/mld.h @@ -204,6 +204,15 @@ xcalloc(object_db_t* object_db, char* struct_name, int units); +/*****API to calloc the object******/ + + +/*****API to calloc the object******/ + +void +xfree(object_db_t* object_db, void* ptr); + + /*****API to calloc the object******/ @@ -211,16 +220,35 @@ xcalloc(object_db_t* object_db, char* struct_name, int units); /*****APIs to register root objects******/ void -mld_register_root_object(object_db_t* object_db, +mld_register_global_object_as_root(object_db_t* object_db, void* objptr, char* struct_name, unsigned int units); void -set_mld_object_as_global_root(object_db_t* object_db, void* obj_ptr); +mld_set_dynamic_object_as_root(object_db_t* object_db, void* obj_ptr); /*****APIs to register root objects******/ + +/*********************************************APIs' to implement MLD algorithm*************************************************/ + +void +report_leaked_objects(object_db_t* object_db); + +/*********************************************APIs' to implement MLD algorithm*************************************************/ + + +/********Adding support for primitive data type********/ + +void +run_mld_algorithm(object_db_t* object_db); + +void +mld_init_primitive_data_types_support(struct_db_t* struct_db); + +/********Adding support for primitive data type********/ + /* * Declaration for OBJECT DATABASE */ diff --git a/src/mld.c b/src/mld.c index e032311..fd24ce5 100644 --- a/src/mld.c +++ b/src/mld.c @@ -4,6 +4,7 @@ #include "css.h" #include #include +#include char* DATA_TYPE[] = { "UINT8", "UINT32", "INT32", "CHAR", "OBJ_PTR", "VOID_PTR", "FLOAT", @@ -87,13 +88,16 @@ add_structure_to_struct_db(struct_db_t* struct_db, struct_db_rec_t* struct_rec) /******Function to lookup the structure record in structure db******/ /*return pointer of struct_db_rec_t on success, NULL on failure from some reason*/ -static struct_db_rec_t* +struct_db_rec_t* struct_db_look_up(struct_db_t* struct_db, char* struct_name) { if (!struct_db || !struct_name) return NULL; struct_db_rec_t* struct_rec = struct_db->head; + + if (!struct_rec) + return NULL; unsigned int sz_db = struct_db->count; @@ -138,7 +142,7 @@ object_db_look_up(object_db_t* object_db, while (i < sz_db) { if (head->ptr == ptr) { - desired_obj = head->ptr; + desired_obj = head; break; } @@ -149,4 +153,416 @@ object_db_look_up(object_db_t* object_db, return desired_obj; } -/******Function to lookup the object record in object db******/ \ No newline at end of file +/******Function to lookup the object record in object db******/ + + + +/******Function to add object to OBJECT DB*******/ + +static void +add_object_to_object_db(object_db_t* object_db, + void* ptr, + int units, + struct_db_rec_t* struct_rec, + mld_boolean_t is_root) { + + object_db_rec_t* obj_rec = object_db_look_up(object_db, ptr); + + /**Don't add some object twice**/ + assert(!obj_rec); + + obj_rec = calloc(1, sizeof(object_db_rec_t)); + + obj_rec->next = NULL; + obj_rec->ptr = ptr; + obj_rec->units = units; + obj_rec->struct_rec = struct_rec; + obj_rec->is_visited = MLD_FALSE; + obj_rec->is_root = is_root; + + object_db_rec_t* head = object_db->head; + + if (!head) { + object_db->head = obj_rec; + obj_rec->next = NULL; + object_db->count++; + return; + } + + + obj_rec->next = head; + object_db->head = obj_rec; + object_db->count++; + +} + +void* +xcalloc(object_db_t* object_db, + char* struct_name, + int units) { + + struct_db_rec_t* struct_rec = struct_db_look_up(object_db->struct_db, struct_name); + assert(struct_rec); + void* ptr = calloc(units, struct_rec->ds_size); + add_object_to_object_db(object_db, ptr, units, + struct_rec, MLD_FALSE); + /*xcalloc by default set the object as non-root*/ + return ptr; + +} + +/******Function to add object to OBJECT DB*******/ + + + +/******Function to delete object record from object db******/ + + +static void +delete_object_record_from_object_db(object_db_t* object_db, + object_db_rec_t* object_rec) { + + assert(object_rec); + + object_db_rec_t* head = object_db->head; + if (head == object_rec) { + object_db->head = object_rec->next; + free(object_rec); + return; + } + + object_db_rec_t* prev = head; + head = head->next; + + while (head) { + if (head != object_rec) { + prev = head; + head = head->next; + continue; + } + + prev->next = head->next; + head->next = NULL; + free(head); + return; + } + +} + + +void +xfree(object_db_t* object_db, void* ptr) { + + if (!ptr) + return; + + object_db_rec_t* object_rec = + object_db_look_up(object_db, ptr); + + assert(object_rec); + assert(object_rec->ptr); + free(object_rec->ptr); + object_rec->ptr = NULL; + + /*Delete object record from object db*/ + delete_object_record_from_object_db(object_db, object_rec); + +} + +/******Function to delete object record from object db******/ + + + + + +/****Printing functions for dumping object db****/ + +void +print_object_rec(object_db_rec_t* obj_rec, int i) { + + if (!obj_rec) + return; + + printf(ANSI_COLOR_MAGENTA "|-------------------------------------------------------------------------------------------------------------|\n"ANSI_COLOR_RESET); + printf(ANSI_COLOR_YELLOW "|%-3d ptr = %-10p | next = %-10p | units = %-4d | struct_name = %-10s | is_root = %s |\n"ANSI_COLOR_RESET, + i, obj_rec->ptr, obj_rec->next, obj_rec->units, obj_rec->struct_rec->struct_name, obj_rec->is_root == MLD_TRUE? "TRUE " : "FALSE"); + printf(ANSI_COLOR_MAGENTA "|-------------------------------------------------------------------------------------------------------------|\n"ANSI_COLOR_RESET); + +} + +void +print_object_db(object_db_t* object_db) { + + + object_db_rec_t* object_rec = object_db->head; + unsigned int i = 0; + printf(ANSI_COLOR_CYAN "Printing OBJECT DATABASE\n" ANSI_COLOR_RESET); + for (; object_rec; object_rec = object_rec->next) { + print_object_rec(object_rec, i++); + } + +} + +/****Printing functions for dumping object db****/ + + + +/*****APIs to register root objects******/ + +/*** + +This API is used to register global object of certain as root object, which are global in scope. +Object is not initialized by xcalloc() function. + +***/ + +void +mld_register_global_object_as_root(object_db_t* object_db, + void* objptr, + char* struct_name, + unsigned int units) { + + struct_db_rec_t* req_struct_rec = struct_db_look_up(object_db->struct_db, struct_name); + + assert(req_struct_rec); + + /*Create a new object record and add it to object database with it being a root object*/ + add_object_to_object_db(object_db, objptr, units, req_struct_rec, MLD_TRUE); + +} + +void +mld_set_dynamic_object_as_root(object_db_t* object_db, void* obj_ptr) { + + + object_db_rec_t* req_obj_rec = object_db_look_up(object_db, obj_ptr); + + assert(req_obj_rec != NULL); + + + req_obj_rec->is_root = MLD_TRUE; + +} + +/*****APIs to register root objects******/ + + + +/************************************************APIs' to implement MLD algorithm***************************************************/ + + +static object_db_rec_t* +get_next_root_object(object_db_t* object_db, object_db_rec_t* last_root_object) { + + object_db_rec_t* cur_obj_rec = last_root_object ? last_root_object->next : object_db->head; + + //assert(cur_obj_rec); + + while (cur_obj_rec) { + + if (cur_obj_rec->is_root == MLD_TRUE) + return cur_obj_rec; + + cur_obj_rec = cur_obj_rec->next; + } + + return NULL; +} + + +static void +init_mld_algorithm(object_db_t* object_db) { + + object_db_rec_t* cur_obj = object_db->head; + + while (cur_obj) { + cur_obj->is_visited = MLD_FALSE; + cur_obj = cur_obj->next; + } +} + +//DFS algorithm to explore the Graphically oriented object set... +static void +mld_explore_object_recursively(object_db_t* object_db, + object_db_rec_t* parent_obj_rec) { + + unsigned int i, n_fields; + char* parent_obj_ptr = NULL, + * child_obj_offset = NULL; + void* child_object_address = NULL; + field_info_t* field_info = NULL; + + object_db_rec_t* child_object_rec = NULL; + struct_db_rec_t* parent_struct_rec = parent_obj_rec->struct_rec; + + /*Parent object must have already visited*/ + + assert(parent_obj_rec->is_visited == MLD_TRUE); + + if (parent_struct_rec->n_fields == 0) { + return; + } + + for (i = 0; i < parent_obj_rec->units; i++) { + + parent_obj_ptr = (char*)(parent_obj_rec->ptr) + (i * parent_struct_rec->ds_size); + + for (n_fields = 0; n_fields < parent_struct_rec->n_fields; n_fields++) { + + field_info = &parent_struct_rec->fields[n_fields]; + + /*Only need to handle void* and obj_ptr*/ + switch (field_info->dtype) { + case UINT8: + case UINT32: + case INT32: + case CHAR: + case FLOAT: + case DOUBLE: + case OBJ_STRUCT: + break; + case VOID_PTR: + case OBJ_PTR: + default: + + + /*child_obj_offset is the memory location inside parent object + where address of next level object is stored*/ + + child_obj_offset = parent_obj_ptr + field_info->offset; + memcpy(&child_object_address, child_obj_offset, sizeof(void*)); + + /*child_obj_address now stores the address of the next object in the graph. + It could be NULL, Handle that as well*/ + + if (!child_object_address) + continue; + + child_object_rec = object_db_look_up(object_db, child_object_address); + + assert(child_object_rec); + + /*Since it's a valid child object of the given parent object, + explore it with leisure for memory leak*/ + if (child_object_rec->is_visited == MLD_FALSE) { + child_object_rec->is_visited = MLD_TRUE; + if (field_info->dtype != VOID_PTR)/*Explore next object only when it is not a VOID_PTR*/ + mld_explore_object_recursively(object_db, child_object_rec); + + } + else { + continue; /*Do nothing, explore next child object*/ + } + } + } + } +} + + +/** Public API to run MLD Algorithm **/ +void +run_mld_algorithm(object_db_t* object_db) { + + //Necessary initialisation... + init_mld_algorithm(object_db); + + //Get the first root object... + object_db_rec_t* root_obj = get_next_root_object(object_db, NULL); + + while (root_obj) { + if (root_obj->is_visited == MLD_TRUE) { + //Exploration from this node object is already done... + root_obj = get_next_root_object(object_db, root_obj); + continue; + } + + root_obj->is_visited = MLD_TRUE; + + mld_explore_object_recursively(object_db, root_obj); + + root_obj = get_next_root_object(object_db, root_obj); + } +} + +static void +mld_dump_object_rec_detail(object_db_rec_t* obj_rec) { + + int n_fields = obj_rec->struct_rec->n_fields; + + field_info_t* field = NULL; + + int units = obj_rec->units, obj_index = 0, + field_index = 0; + + for (; obj_index < units; obj_index++) { + char* current_object_ptr = (char*)(obj_rec->ptr) + + (obj_index * obj_rec->struct_rec->ds_size); + + for (field_index = 0; field_index < n_fields; field_index++) { + + field = &obj_rec->struct_rec->fields[field_index]; + + switch (field->dtype) { + case UINT8: + case INT32: + case UINT32: + printf("%s[%d]->%s = %d\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, *(int*)(current_object_ptr + field->offset)); + break; + case CHAR: + printf("%s[%d]->%s = %s\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, (char*)(current_object_ptr + field->offset)); + break; + case FLOAT: + printf("%s[%d]->%s = %f\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, *(float*)(current_object_ptr + field->offset)); + break; + case DOUBLE: + printf("%s[%d]->%s = %f\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, *(double*)(current_object_ptr + field->offset)); + break; + case OBJ_PTR: + printf("%s[%d]->%s = %p\n", obj_rec->struct_rec->struct_name, obj_index, field->fname, (void*)*(int*)(current_object_ptr + field->offset)); + break; + case OBJ_STRUCT: + /*Later*/ + break; + default: + break; + } + } + } +} + +void +report_leaked_objects(object_db_t* object_db) { + + int i = 0; + object_db_rec_t* head; + + printf("Dumping Leaked Objects\n"); + + for (head = object_db->head; head; head = head->next) { + if (head->is_visited == MLD_FALSE) { + print_object_rec(head, i++); + mld_dump_object_rec_detail(head); + printf("\n\n"); + } + } +} + + + +/************************************************APIs' to implement MLD algorithm***************************************************/ + + + + +/********Adding support for primitive data type********/ + +void +mld_init_primitive_data_types_support(struct_db_t* struct_db) { + + REG_STRUCT(struct_db, int, 0); + REG_STRUCT(struct_db, float, 0); + REG_STRUCT(struct_db, double, 0); + +} + +/********Adding support for primitive data type********/