#include "object_info.h"
#include "xmalloc.h"
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <stdarg.h>
static void object_info_init_va(struct object_info_struct *object_info, const char *name, int type, va_list ap)
{
const char *filename;
object_info->name = xstrdup(name);
switch ((object_info->type = type)) {
case OI_EXEC:
object_info->filename = NULL;
break;
case OI_FILE:
object_info->filename = xstrdup(va_arg(ap, const char *));
object_info->dev = va_arg(ap, dev_t);
object_info->ino = va_arg(ap, ino_t);
break;
case OI_VDSO:
object_info->filename = NULL;
break;
case OI_DYNAMIC_LINKER:
if ((filename = va_arg(ap, const char *)))
object_info->filename = xstrdup(filename);
else
object_info->filename = NULL;
break;
case OI_NOT_FOUND:
object_info->filename = NULL;
break;
}
object_info->base_address = MAP_FAILED;
object_info->load_address = MAP_FAILED;
object_info->segment_table = NULL;
object_info->segment_count = 0;
clear_dynamic_data(&object_info->dynamic_data);
object_info->dependency_list = NULL;
object_info->dependency_list_size = 0;
object_info->reference_count = 0;
}
void object_info_init(struct object_info_struct *object_info, const char *name, int type, ...)
{
va_list ap;
va_start(ap, type);
object_info_init_va(object_info, name, type, ap);
va_end(ap);
}
void object_info_destroy(struct object_info_struct *object_info)
{
if (object_info->segment_table)
free(object_info->segment_table);
if (object_info->dependency_list)
free(object_info->dependency_list);
dispose_dynamic_data(&object_info->dynamic_data);
if (object_info->filename)
free(object_info->filename);
free(object_info->name);
}
int object_info_equals(struct object_info_struct *object_info1, struct object_info_struct *object_info2)
{
if (!strcmp(object_info1->name, object_info2->name))
return 1;
if (object_info1->type != object_info2->type)
return 0;
switch (object_info1->type) {
case OI_EXEC:
return 1;
case OI_FILE:
return object_info1->dev == object_info2->dev && object_info1->ino == object_info2->ino;
case OI_DYNAMIC_LINKER:
return 1;
case OI_VDSO:
case OI_NOT_FOUND:
default:
return 0;
}
}
void object_info_print(struct object_info_struct *object_info)
{
printf("\t");
if (!object_info->filename || strcmp(object_info->name, object_info->filename))
printf("%s => ", object_info->name);
if (object_info->type == OI_NOT_FOUND)
printf("not found\n");
else {
if (object_info->filename)
printf("%s", object_info->filename);
printf(" (0x%0*lx)\n", 2 * sizeof (unsigned long), (unsigned long)object_info->load_address);
}
}
void object_info_list_init(struct object_info_list_struct *object_info_list)
{
object_info_list->first = NULL;
object_info_list->last = NULL;
}
void object_info_list_destroy(struct object_info_list_struct *object_info_list)
{
struct object_info_struct *object_info, *next_object_info;
for (object_info = object_info_list->first; object_info; object_info = next_object_info) {
next_object_info = object_info->next;
object_info_destroy(object_info);
free(object_info);
}
}
struct object_info_struct *object_info_list_insert(struct object_info_list_struct *object_info_list, const char *name, int type, ...)
{
va_list ap;
struct object_info_struct *object_info;
struct object_info_struct *object_info1, *object_info2;
object_info = xmalloc(sizeof (struct object_info_struct));
va_start(ap, type);
object_info_init_va(object_info, name, type, ap);
va_end(ap);
object_info1 = NULL;
object_info2 = object_info_list->first;
while (object_info2) {
if (object_info_equals(object_info2, object_info)) {
object_info_destroy(object_info);
free(object_info);
return object_info2;
}
object_info1 = object_info2;
object_info2 = object_info2->next;
}
object_info->previous = object_info1;
object_info->next = NULL;
if (object_info1)
object_info1->next = object_info;
else
object_info_list->first = object_info;
object_info_list->last = object_info;
return object_info;
}