radare2/libr/bin/pdb/omap.c
2019-11-10 14:06:02 +08:00

135 lines
3.3 KiB
C

/* radare - LGPL - Copyright 2014-2016 - iniside, pancake */
#include "types.h"
#include "omap.h"
#include "stream_file.h"
static int parse_omap_entry(char *data, int data_size, int *read_bytes, SOmapEntry *omap_entry) {
int curr_read_bytes = *read_bytes;
memcpy (omap_entry, data, sizeof (SOmapEntry));
*read_bytes += sizeof (SOmapEntry);
return (*read_bytes - curr_read_bytes);
}
void parse_omap_stream(void *stream, R_STREAM_FILE *stream_file) {
int data_size;
char *data = NULL, *ptmp = NULL;
int curr_read_bytes = 0, read_bytes = 0;
SOmapEntry *omap_entry = 0;
SOmapStream *omap_stream = 0;
stream_file_get_size (stream_file, &data_size);
data = (char *) malloc (data_size);
if (!data) {
return;
}
stream_file_get_data (stream_file, data);
omap_stream = (SOmapStream *) stream;
omap_stream->froms = 0;
omap_stream->omap_entries = r_list_new ();
ptmp = data;
while (read_bytes < data_size) {
omap_entry = (SOmapEntry *) malloc (sizeof(SOmapEntry));
if (!omap_entry) {
break;
}
curr_read_bytes = parse_omap_entry (ptmp, data_size, &read_bytes, omap_entry);
if (!curr_read_bytes) {
free (omap_entry);
break;
}
ptmp += curr_read_bytes;
r_list_append (omap_stream->omap_entries, omap_entry);
}
free (data);
}
void free_omap_stream(void *stream) {
SOmapStream *omap_stream = (SOmapStream *) stream;
SOmapEntry *omap_entry = NULL;
RListIter *it = r_list_iterator (omap_stream->omap_entries);
while (r_list_iter_next (it)) {
omap_entry = (SOmapEntry *) r_list_iter_get (it);
free (omap_entry);
}
r_list_free (omap_stream->omap_entries);
}
// inclusive indices
// 0 <= imin when using truncate toward zero divide
// imid = (imin+imax)/2;
// imin unrestricted when using truncate toward minus infinity divide
// imid = (imin+imax)>>1; or
// imid = (int)floor((imin+imax)/2.0);
static int binary_search(unsigned int *A, int key, int imin, int imax) {
int imid;
// continually narrow search until just one element remains
while (imin < imax) {
imid = (imin + imax) / 2;
if (A[imid] < key) {
imin = imid + 1;
} else {
imax = imid;
}
}
// At exit of while:
// if A[] is empty, then imax < imin
// otherwise imax == imin
// deferred test for equality
if ((imax == imin) && (A[imin] == key)) {
return imin;
}
return -1;
}
int omap_remap(void *stream, int address) {
SOmapStream *omap_stream = (SOmapStream *) stream;
SOmapEntry *omap_entry = 0;
RListIter *it = 0;
int i = 0;
int pos = 0;
int len = 0;
if (!omap_stream) {
return address;
}
len = r_list_length (omap_stream->omap_entries);
if (omap_stream->froms == 0) {
omap_stream->froms = (unsigned int *) malloc (4 * len);
if (!omap_stream->froms) {
return -1;
}
it = r_list_iterator (omap_stream->omap_entries);
while (r_list_iter_next (it)) {
omap_entry = (SOmapEntry *) r_list_iter_get (it);
omap_stream->froms[i] = omap_entry->from;
i++;
}
}
// mb (len -1) ???
pos = binary_search (omap_stream->froms, address, 0, (len));
if (pos == -1) {
return -1;
}
if (omap_stream->froms[pos] != address) {
pos -= 1;
}
omap_entry = (SOmapEntry *) r_list_get_n (omap_stream->omap_entries, pos);
if (!omap_entry) {
return -1;
}
if (omap_entry->to == 0) {
return omap_entry->to;
}
return omap_entry->to + (address - omap_entry->from);
}