mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-19 13:53:07 +00:00
135 lines
3.3 KiB
C
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);
|
|
}
|