Rizin
unix-like reverse engineering framework and cli tools
dbginfo.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2020 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2021 thestr4ng3r <info@florianmaerkl.de>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <rz_types.h>
7 #include <rz_bin.h>
8 
12 }
13 
15  rz_vector_fini(&builder->samples);
17 }
18 
29  RzBinSourceLineSample *sample = rz_vector_push(&builder->samples, NULL);
30  if (!sample) {
31  return;
32  }
33  sample->address = address;
34  sample->line = line;
35  sample->column = column;
36  sample->file = file ? rz_str_constpool_get(&builder->filename_pool, file) : NULL;
37 }
38 
39 static int line_sample_cmp(const void *a, const void *b) {
40  const RzBinSourceLineSample *sa = a;
41  const RzBinSourceLineSample *sb = b;
42  // first, sort by addr
43  if (sa->address < sb->address) {
44  return -1;
45  }
46  if (sa->address > sb->address) {
47  return 1;
48  }
49  // closing samples are always equal (rest of their fields are ignored anyway)
51  return 0;
52  }
53  // push closing samples to the back, which is necessary to skip them during packing
55  return 1;
56  }
58  return -1;
59  }
60  // then sort by line
61  if (sa->line < sb->line) {
62  return -1;
63  }
64  if (sa->line > sb->line) {
65  return 1;
66  }
67  // then by column
68  if (sa->column < sb->column) {
69  return -1;
70  }
71  if (sa->column > sb->column) {
72  return 1;
73  }
74  // and eventually by file because this is the most exponsive operation
75  if (!sa->file && !sb->file) {
76  return 0;
77  }
78  if (!sa->file) {
79  return -1;
80  }
81  if (!sb->file) {
82  return 1;
83  }
84  return strcmp(sa->file, sb->file);
85 }
86 
89  if (!r) {
90  goto err;
91  }
92  size_t initial_samples_count = rz_vector_len(&builder->samples); // final count may be less after removing unnecessary closing samples
93  if (initial_samples_count) {
94  r->samples = RZ_NEWS0(RzBinSourceLineSample, initial_samples_count);
95  if (!r->samples) {
96  goto err_r;
97  }
98 
99  // samples should be built in flat RzVector to avoid excessive small mallocs,
100  // for sorting we use a pvector with references into our flat vectors (after flushing them).
101 
102  RzPVector sorter;
103  rz_pvector_init(&sorter, NULL);
104  RzBinSourceLineSample *initial_samples = rz_vector_flush(&builder->samples);
105  rz_pvector_reserve(&sorter, initial_samples_count);
106  for (size_t i = 0; i < initial_samples_count; i++) {
107  rz_pvector_push(&sorter, &initial_samples[i]);
108  }
110 
111  r->samples_count = 0;
112  for (size_t i = 0; i < initial_samples_count; i++) {
113  RzBinSourceLineSample *new_sample = rz_pvector_at(&sorter, i);
114  if (r->samples_count) {
115  RzBinSourceLineSample *prev = &r->samples[r->samples_count - 1];
116  if (prev->address == new_sample->address && rz_bin_source_line_sample_is_closing(new_sample)) {
117  // closing sample but there are others that are not closing so this is dropped
118  continue;
119  }
120  }
121  r->samples[r->samples_count++] = *new_sample;
122  }
123  free(initial_samples); // all inner strings are moved already
124  rz_pvector_fini(&sorter);
125  }
126  r->filename_pool = builder->filename_pool;
127  // don't call regular fini on the builder because we moved its string pool!
128  rz_vector_fini(&builder->samples);
129  return r;
130 err_r:
131  free(r);
132 err:
134  return NULL;
135 }
136 
138  if (!sli) {
139  return;
140  }
141  free(sli->samples);
143  free(sli);
144 }
145 
152  if (!sli->samples_count) {
153  return NULL;
154  }
155  size_t l;
156 #define CMP(x, y) (x > y.address ? 1 : (x < y.address ? -1 : 0))
158 #undef CMP
159  if (!l) {
160  return NULL;
161  }
162  l--;
163  RzBinSourceLineSample *r = &sli->samples[l];
164  if (r->address > addr || rz_bin_source_line_sample_is_closing(r)) {
165  return NULL;
166  }
167  // walk back to the very first entry with this addr
168  while (r > sli->samples) {
169  if ((r - 1)->address == r->address) {
170  r--;
171  } else {
172  break;
173  }
174  }
175  return r;
176 }
177 
183  rz_return_val_if_fail(sli && cur && cur >= sli->samples && cur < sli->samples + sli->samples_count, NULL);
184  if (cur == sli->samples + sli->samples_count - 1) {
185  return NULL;
186  }
187  const RzBinSourceLineSample *next = cur + 1;
188  if (next->address != cur->address) {
189  return NULL;
190  }
191  return next;
192 }
193 
195  rz_return_val_if_fail(bin, false);
196  if (!bin->cur || !bin->cur->o || !bin->cur->o->lines) {
197  return false;
198  }
200  if (!s || s->address != addr) {
201  // consider only exact matches, not inside of samples
202  return false;
203  }
204  if (line) {
205  *line = s->line;
206  }
207  if (file && len) {
208  if (s->file) {
209  rz_str_ncpy(file, s->file, len);
210  } else {
211  *file = 0;
212  }
213  }
214  return false;
215 }
216 
219  if (!bin->cur || !bin->cur->o || !bin->cur->o->lines) {
220  return NULL;
221  }
223  if (s && s->address != addr) {
224  // consider only exact matches, not inside of samples
225  return NULL;
226  }
227  while (s && !s->file) {
228  s = rz_bin_source_line_info_get_next(bin->cur->o->lines, s);
229  }
230  if (!s) {
231  return NULL;
232  }
233  const char *file_nopath;
234  if (origin > 1) {
235  file_nopath = s->file;
236  } else {
237  file_nopath = strrchr(s->file, '/');
238  if (file_nopath) {
239  file_nopath++;
240  } else {
241  file_nopath = s->file;
242  }
243  }
244  if (!s->line) {
245  return strdup(file_nopath);
246  }
247  char *out = rz_file_slurp_line(s->file, s->line, 0);
248  if (out) {
249  rz_str_trim(out);
250  if (origin) {
251  char *res = rz_str_newf("%s:%d %s",
252  file_nopath, s->line,
253  out ? out : "");
254  free(out);
255  out = res;
256  }
257  return out;
258  }
259  return rz_str_newf("%s:%" PFMT32u, file_nopath, s->line);
260 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
static SblHeader sb
Definition: bin_mbn.c:26
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
RZ_API void rz_bin_source_line_info_free(RzBinSourceLineInfo *sli)
Definition: dbginfo.c:137
RZ_API const RzBinSourceLineSample * rz_bin_source_line_info_get_next(const RzBinSourceLineInfo *sli, RZ_NONNULL const RzBinSourceLineSample *cur)
Definition: dbginfo.c:182
RZ_DEPRECATE RZ_API bool rz_bin_addr2line(RzBin *bin, ut64 addr, char *file, int len, int *line)
Definition: dbginfo.c:194
static int line_sample_cmp(const void *a, const void *b)
Definition: dbginfo.c:39
RZ_API void rz_bin_source_line_info_builder_init(RzBinSourceLineInfoBuilder *builder)
Definition: dbginfo.c:9
RZ_API void rz_bin_source_line_info_builder_fini(RzBinSourceLineInfoBuilder *builder)
Definition: dbginfo.c:14
RZ_API RzBinSourceLineInfo * rz_bin_source_line_info_builder_build_and_fini(RzBinSourceLineInfoBuilder *builder)
Definition: dbginfo.c:87
RZ_API const RzBinSourceLineSample * rz_bin_source_line_info_get_first_at(const RzBinSourceLineInfo *sli, ut64 addr)
Find the first sample that affects the given address. i.e. find the first sample with the highest add...
Definition: dbginfo.c:151
RZ_DEPRECATE RZ_API char * rz_bin_addr2text(RzBin *bin, ut64 addr, int origin)
Definition: dbginfo.c:217
RZ_API void rz_bin_source_line_info_builder_push_sample(RzBinSourceLineInfoBuilder *builder, ut64 address, ut32 line, ut32 column, const char *file)
Push a new sample into the builder.
Definition: dbginfo.c:28
#define CMP(x, y)
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong int origin
Definition: ioapi.h:144
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
line
Definition: setup.py:34
static RzSocket * s
Definition: rtr.c:28
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static bool rz_bin_source_line_sample_is_closing(const RzBinSourceLineSample *s)
Definition: rz_bin.h:474
RZ_API bool RZ_API char * rz_file_slurp_line(const char *file, int line, int context)
Definition: file.c:673
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190
RZ_API const char * rz_str_constpool_get(RzStrConstPool *pool, const char *str)
Definition: str_constpool.c:19
RZ_API void rz_str_constpool_fini(RzStrConstPool *pool)
Definition: str_constpool.c:15
RZ_API bool rz_str_constpool_init(RzStrConstPool *pool)
Definition: str_constpool.c:10
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define PFMT32u
Definition: rz_types.h:409
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_DEPRECATE
Definition: rz_types.h:66
static void ** rz_pvector_reserve(RzPVector *vec, size_t capacity)
Definition: rz_vector.h:312
RZ_API void rz_pvector_sort(RzPVector *vec, RzPVectorComparator cmp)
Definition: vector.c:408
RZ_API void * rz_vector_flush(RzVector *vec)
Turn the vector into a fixed-size array. This will clear the vector and return an array of its origin...
Definition: vector.c:230
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
RZ_API void rz_pvector_fini(RzPVector *vec)
Definition: vector.c:331
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
#define rz_array_upper_bound(array, len, x, i, cmp)
Definition: rz_vector.h:374
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
Definition: malloc.c:26
Definition: gzappend.c:170
RzStrConstPool filename_pool
Definition: rz_bin.h:496
RzStrConstPool filename_pool
Definition: rz_bin.h:488
RzBinSourceLineSample * samples
All source line references for given adresses.
Definition: rz_bin.h:486
A single sample of source line info for a specific address.
Definition: rz_bin.h:441
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58