Standardize `!ptr` i/o `ptr == NULL`, `ptr` i/o `ptr != NULL`
[babeltrace.git] / tests / plugins / flt.lttng-utils.debug-info / test_bin_info.c
CommitLineData
6ab5bdaa 1/*
d5ddf820 2 * test_bin_info.c
6ab5bdaa
AB
3 *
4 * Babeltrace SO info tests
5 *
6 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
7 * Copyright (c) 2015 Antoine Busque <abusque@efficios.com>
882adb99 8 * Copyright (c) 2019 Michael Jeanson <mjeanson@efficios.com>
6ab5bdaa
AB
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; under version 2 of the License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
770538dd 24#define BT_LOG_OUTPUT_LEVEL BT_LOG_WARNING
86d8b7b8
PP
25#define BT_LOG_TAG "TEST/BIN-INFO"
26#include "logging/log.h"
27
6ab5bdaa
AB
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
882adb99
MJ
31#include <inttypes.h>
32#include <glib.h>
1e638f98 33
91d81473 34#include "common/macros.h"
578e048b 35#include "common/assert.h"
c283522b 36#include <lttng-utils/debug-info/bin-info.h>
1e638f98 37
6ab5bdaa
AB
38#include "tap/tap.h"
39
882adb99
MJ
40#define NR_TESTS 57
41
24d3147c 42#define SO_NAME "libhello_so"
882adb99
MJ
43#define DEBUG_NAME "libhello_so.debug"
44#define FUNC_FOO_FILENAME "./libhello.c"
45#define FUNC_FOO_PRINTF_NAME_FMT "foo+0x%" PRIx64
46#define FUNC_FOO_NAME_LEN 64
6a284733
MJ
47
48#define DWARF_DIR_NAME "dwarf_full"
49#define ELF_DIR_NAME "elf_only"
50#define BUILDID_DIR_NAME "build_id"
51#define DEBUGLINK_DIR_NAME "debug_link"
52
882adb99 53/* Lower bound of PIC address mapping */
6ab5bdaa 54#define SO_LOW_ADDR 0x400000
882adb99
MJ
55/* Size of PIC address mapping */
56#define SO_MEMSZ 0x800000
57/* An address outside the PIC mapping */
58#define SO_INV_ADDR 0x200000
59
60#define BUILD_ID_HEX_LEN 20
61
62static uint64_t opt_func_foo_addr;
63static uint64_t opt_func_foo_printf_offset;
64static uint64_t opt_func_foo_printf_line_no;
65static uint64_t opt_func_foo_tp_offset;
66static uint64_t opt_func_foo_tp_line_no;
67static uint64_t opt_debug_link_crc;
68static gchar *opt_build_id;
69static gchar *opt_debug_info_dir;
70
71static uint64_t func_foo_printf_addr;
72static uint64_t func_foo_tp_addr;
73static char func_foo_printf_name[FUNC_FOO_NAME_LEN];
74static uint8_t build_id[BUILD_ID_HEX_LEN];
75
76static GOptionEntry entries[] = {
77 {"foo-addr", 0, 0, G_OPTION_ARG_INT64, &opt_func_foo_addr,
78 "Offset to printf in foo", "0xX"},
79 {"printf-offset", 0, 0, G_OPTION_ARG_INT64, &opt_func_foo_printf_offset,
80 "Offset to printf in foo", "0xX"},
81 {"printf-lineno", 0, 0, G_OPTION_ARG_INT64,
82 &opt_func_foo_printf_line_no, "Line number to printf in foo", "N"},
83 {"tp-offset", 0, 0, G_OPTION_ARG_INT64, &opt_func_foo_tp_offset,
84 "Offset to tp in foo", "0xX"},
85 {"tp-lineno", 0, 0, G_OPTION_ARG_INT64, &opt_func_foo_tp_line_no,
86 "Line number to tp in foo", "N"},
87 {"debug-link-crc", 0, 0, G_OPTION_ARG_INT64, &opt_debug_link_crc,
88 "Debug link CRC", "0xX"},
89 {"build-id", 0, 0, G_OPTION_ARG_STRING, &opt_build_id, "Build ID",
90 "XXXXXXXXXXXXXXX"},
91 {"debug-info-dir", 0, 0, G_OPTION_ARG_STRING, &opt_debug_info_dir,
92 "Debug info directory", NULL},
93 {NULL}};
94
95static
96int build_id_to_bin(void)
97{
98 int ret, len, i;
99
5084732e 100 if (!opt_build_id) {
882adb99
MJ
101 goto error;
102 }
103
104 len = strnlen(opt_build_id, BUILD_ID_HEX_LEN * 2);
105 if (len != (BUILD_ID_HEX_LEN * 2)) {
106 goto error;
107 }
108
109 for (i = 0; i < (len / 2); i++) {
110 ret = sscanf(opt_build_id + 2 * i, "%02hhx", &build_id[i]);
111 if (ret != 1) {
112 goto error;
113 }
114 }
115
116 if (i != BUILD_ID_HEX_LEN) {
117 goto error;
118 }
119
120 return 0;
121error:
122 return -1;
123}
124
125static
126void subtest_has_address(struct bin_info *bin, uint64_t addr)
127{
128 int ret;
129
130 ret = bin_info_has_address(bin, SO_LOW_ADDR - 1);
131 ok(ret == 0, "bin_info_has_address - address under SO's range");
132
133 ret = bin_info_has_address(bin, SO_LOW_ADDR);
134 ok(ret == 1, "bin_info_has_address - lower bound of SO's range");
135
136 ret = bin_info_has_address(bin, addr);
137 ok(ret == 1, "bin_info_has_address - address in SO's range");
138
139 ret = bin_info_has_address(bin, SO_LOW_ADDR + SO_MEMSZ - 1);
140 ok(ret == 1, "bin_info_has_address - upper bound of SO's range");
141
142 ret = bin_info_has_address(bin, SO_LOW_ADDR + SO_MEMSZ);
143 ok(ret == 0, "bin_info_has_address - address above SO's range");
144}
145
146static
147void subtest_lookup_function_name(struct bin_info *bin, uint64_t addr,
148 char *func_name)
149{
150 int ret;
151 char *_func_name = NULL;
152
153 ret = bin_info_lookup_function_name(bin, addr, &_func_name);
154 ok(ret == 0, "bin_info_lookup_function_name successful at 0x%x", addr);
155 if (_func_name) {
156 ok(strcmp(_func_name, func_name) == 0,
157 "bin_info_lookup_function_name - correct function name (%s == %s)",
158 func_name, _func_name);
159 free(_func_name);
160 _func_name = NULL;
161 } else {
162 skip(1,
163 "bin_info_lookup_function_name - function name is NULL");
164 }
165
166 /* Test function name lookup - erroneous address */
167 ret = bin_info_lookup_function_name(bin, SO_INV_ADDR, &_func_name);
5084732e 168 ok(ret == -1 && !_func_name,
882adb99 169 "bin_info_lookup_function_name - fail on invalid addr");
6b934a94 170 free(_func_name);
882adb99
MJ
171}
172
173static
174void subtest_lookup_source_location(struct bin_info *bin, uint64_t addr,
175 uint64_t line_no, char *filename)
176{
177 int ret;
178 struct source_location *src_loc = NULL;
179
180 ret = bin_info_lookup_source_location(bin, addr, &src_loc);
181 ok(ret == 0, "bin_info_lookup_source_location successful at 0x%x",
182 addr);
183 if (src_loc) {
184 ok(src_loc->line_no == line_no,
185 "bin_info_lookup_source_location - correct line_no (%d == %d)",
186 line_no, src_loc->line_no);
187 ok(strcmp(src_loc->filename, filename) == 0,
188 "bin_info_lookup_source_location - correct filename (%s == %s)",
189 filename, src_loc->filename);
190 source_location_destroy(src_loc);
191 src_loc = NULL;
192 } else {
193 fail("bin_info_lookup_source_location - src_loc is NULL");
194 fail("bin_info_lookup_source_location - src_loc is NULL");
195 }
196
197 /* Test source location lookup - erroneous address */
198 ret = bin_info_lookup_source_location(bin, SO_INV_ADDR, &src_loc);
5084732e 199 ok(ret == -1 && !src_loc,
882adb99
MJ
200 "bin_info_lookup_source_location - fail on invalid addr");
201 if (src_loc) {
202 source_location_destroy(src_loc);
203 }
204}
6ab5bdaa
AB
205
206static
6a284733 207void test_bin_info_build_id(const char *bin_info_dir)
6ab5bdaa
AB
208{
209 int ret;
6a284733 210 char *data_dir, *bin_path;
d5ddf820 211 struct bin_info *bin = NULL;
1e638f98 212 struct bt_fd_cache fdc;
882adb99
MJ
213 uint8_t invalid_build_id[BUILD_ID_HEX_LEN] = {
214 0xa3, 0xfd, 0x8b, 0xff, 0x45, 0xe1, 0xa9, 0x32, 0x15, 0xdd,
6ab5bdaa
AB
215 0x6d, 0xaa, 0xd5, 0x53, 0x98, 0x7e, 0xaf, 0xd4, 0x0c, 0xbb
216 };
217
d5ddf820 218 diag("bin-info tests - separate DWARF via build ID");
6ab5bdaa 219
6a284733 220 data_dir = g_build_filename(bin_info_dir, BUILDID_DIR_NAME, NULL);
882adb99
MJ
221 bin_path =
222 g_build_filename(bin_info_dir, BUILDID_DIR_NAME, SO_NAME, NULL);
6a284733 223
5084732e 224 if (!data_dir || !bin_path) {
6a284733
MJ
225 exit(EXIT_FAILURE);
226 }
6ab5bdaa 227
86d8b7b8 228 ret = bt_fd_cache_init(&fdc, BT_LOG_OUTPUT_LEVEL);
7de0939d
MJ
229 if (ret != 0) {
230 diag("Failed to initialize FD cache");
231 exit(EXIT_FAILURE);
232 }
6ab5bdaa 233
882adb99 234 bin = bin_info_create(&fdc, bin_path, SO_LOW_ADDR, SO_MEMSZ, true,
91bc8451 235 data_dir, NULL, BT_LOG_OUTPUT_LEVEL, NULL);
5084732e 236 ok(bin, "bin_info_create successful (%s)", bin_path);
882adb99
MJ
237
238 /* Test setting invalid build_id */
239 ret = bin_info_set_build_id(bin, invalid_build_id, BUILD_ID_HEX_LEN);
240 ok(ret == -1, "bin_info_set_build_id fail on invalid build_id");
241
242 /* Test setting correct build_id */
243 ret = bin_info_set_build_id(bin, build_id, BUILD_ID_HEX_LEN);
4caab45b 244 ok(ret == 0, "bin_info_set_build_id successful");
6ab5bdaa 245
882adb99
MJ
246 /* Test bin_info_has_address */
247 subtest_has_address(bin, func_foo_printf_addr);
248
6ab5bdaa 249 /* Test function name lookup (with DWARF) */
882adb99
MJ
250 subtest_lookup_function_name(bin, func_foo_printf_addr,
251 func_foo_printf_name);
6ab5bdaa
AB
252
253 /* Test source location lookup */
882adb99
MJ
254 subtest_lookup_source_location(bin, func_foo_printf_addr,
255 opt_func_foo_printf_line_no,
256 FUNC_FOO_FILENAME);
6ab5bdaa 257
d5ddf820 258 bin_info_destroy(bin);
1e638f98 259 bt_fd_cache_fini(&fdc);
6a284733
MJ
260 g_free(data_dir);
261 g_free(bin_path);
6ab5bdaa
AB
262}
263
264static
6a284733 265void test_bin_info_debug_link(const char *bin_info_dir)
6ab5bdaa
AB
266{
267 int ret;
6a284733 268 char *data_dir, *bin_path;
d5ddf820 269 struct bin_info *bin = NULL;
1e638f98 270 struct bt_fd_cache fdc;
6ab5bdaa 271
d5ddf820 272 diag("bin-info tests - separate DWARF via debug link");
6ab5bdaa 273
6a284733 274 data_dir = g_build_filename(bin_info_dir, DEBUGLINK_DIR_NAME, NULL);
882adb99
MJ
275 bin_path = g_build_filename(bin_info_dir, DEBUGLINK_DIR_NAME, SO_NAME,
276 NULL);
6a284733 277
5084732e 278 if (!data_dir || !bin_path) {
6a284733
MJ
279 exit(EXIT_FAILURE);
280 }
6ab5bdaa 281
86d8b7b8 282 ret = bt_fd_cache_init(&fdc, BT_LOG_OUTPUT_LEVEL);
7de0939d
MJ
283 if (ret != 0) {
284 diag("Failed to initialize FD cache");
285 exit(EXIT_FAILURE);
286 }
882adb99
MJ
287
288 bin = bin_info_create(&fdc, bin_path, SO_LOW_ADDR, SO_MEMSZ, true,
91bc8451 289 data_dir, NULL, BT_LOG_OUTPUT_LEVEL, NULL);
5084732e 290 ok(bin, "bin_info_create successful (%s)", bin_path);
6ab5bdaa
AB
291
292 /* Test setting debug link */
882adb99 293 ret = bin_info_set_debug_link(bin, DEBUG_NAME, opt_debug_link_crc);
4caab45b 294 ok(ret == 0, "bin_info_set_debug_link successful");
6ab5bdaa 295
882adb99
MJ
296 /* Test bin_info_has_address */
297 subtest_has_address(bin, func_foo_printf_addr);
298
6ab5bdaa 299 /* Test function name lookup (with DWARF) */
882adb99
MJ
300 subtest_lookup_function_name(bin, func_foo_printf_addr,
301 func_foo_printf_name);
6ab5bdaa
AB
302
303 /* Test source location lookup */
882adb99
MJ
304 subtest_lookup_source_location(bin, func_foo_printf_addr,
305 opt_func_foo_printf_line_no,
306 FUNC_FOO_FILENAME);
6ab5bdaa 307
d5ddf820 308 bin_info_destroy(bin);
1e638f98 309 bt_fd_cache_fini(&fdc);
6a284733
MJ
310 g_free(data_dir);
311 g_free(bin_path);
6ab5bdaa
AB
312}
313
314static
6a284733 315void test_bin_info_elf(const char *bin_info_dir)
6ab5bdaa
AB
316{
317 int ret;
6a284733 318 char *data_dir, *bin_path;
d5ddf820 319 struct bin_info *bin = NULL;
6ab5bdaa 320 struct source_location *src_loc = NULL;
1e638f98 321 struct bt_fd_cache fdc;
6ab5bdaa 322
d5ddf820 323 diag("bin-info tests - ELF only");
6ab5bdaa 324
6a284733
MJ
325 data_dir = g_build_filename(bin_info_dir, ELF_DIR_NAME, NULL);
326 bin_path = g_build_filename(bin_info_dir, ELF_DIR_NAME, SO_NAME, NULL);
327
5084732e 328 if (!data_dir || !bin_path) {
6a284733
MJ
329 exit(EXIT_FAILURE);
330 }
6ab5bdaa 331
86d8b7b8 332 ret = bt_fd_cache_init(&fdc, BT_LOG_OUTPUT_LEVEL);
7de0939d
MJ
333 if (ret != 0) {
334 diag("Failed to initialize FD cache");
335 exit(EXIT_FAILURE);
336 }
6ab5bdaa 337
882adb99 338 bin = bin_info_create(&fdc, bin_path, SO_LOW_ADDR, SO_MEMSZ, true,
91bc8451 339 data_dir, NULL, BT_LOG_OUTPUT_LEVEL, NULL);
5084732e 340 ok(bin, "bin_info_create successful (%s)", bin_path);
6ab5bdaa 341
882adb99
MJ
342 /* Test bin_info_has_address */
343 subtest_has_address(bin, func_foo_printf_addr);
344
345 /* Test function name lookup (with ELF) */
346 subtest_lookup_function_name(bin, func_foo_printf_addr,
347 func_foo_printf_name);
6ab5bdaa
AB
348
349 /* Test source location location - should fail on ELF only file */
882adb99
MJ
350 ret = bin_info_lookup_source_location(bin, func_foo_printf_addr,
351 &src_loc);
352 ok(ret == -1,
353 "bin_info_lookup_source_location - fail on ELF only file");
6ab5bdaa
AB
354
355 source_location_destroy(src_loc);
d5ddf820 356 bin_info_destroy(bin);
1e638f98 357 bt_fd_cache_fini(&fdc);
6a284733
MJ
358 g_free(data_dir);
359 g_free(bin_path);
6ab5bdaa
AB
360}
361
362static
882adb99 363void test_bin_info_bundled(const char *bin_info_dir)
6ab5bdaa
AB
364{
365 int ret;
6a284733 366 char *data_dir, *bin_path;
d5ddf820 367 struct bin_info *bin = NULL;
1e638f98 368 struct bt_fd_cache fdc;
6ab5bdaa 369
882adb99 370 diag("bin-info tests - DWARF bundled in SO file");
1e638f98 371
6a284733 372 data_dir = g_build_filename(bin_info_dir, DWARF_DIR_NAME, NULL);
882adb99
MJ
373 bin_path =
374 g_build_filename(bin_info_dir, DWARF_DIR_NAME, SO_NAME, NULL);
6a284733 375
5084732e 376 if (!data_dir || !bin_path) {
6a284733
MJ
377 exit(EXIT_FAILURE);
378 }
6ab5bdaa 379
86d8b7b8 380 ret = bt_fd_cache_init(&fdc, BT_LOG_OUTPUT_LEVEL);
7de0939d
MJ
381 if (ret != 0) {
382 diag("Failed to initialize FD cache");
383 exit(EXIT_FAILURE);
384 }
882adb99
MJ
385
386 bin = bin_info_create(&fdc, bin_path, SO_LOW_ADDR, SO_MEMSZ, true,
91bc8451 387 data_dir, NULL, BT_LOG_OUTPUT_LEVEL, NULL);
5084732e 388 ok(bin, "bin_info_create successful (%s)", bin_path);
d5ddf820
AB
389
390 /* Test bin_info_has_address */
882adb99 391 subtest_has_address(bin, func_foo_printf_addr);
6ab5bdaa
AB
392
393 /* Test function name lookup (with DWARF) */
882adb99
MJ
394 subtest_lookup_function_name(bin, func_foo_printf_addr,
395 func_foo_printf_name);
6ab5bdaa
AB
396
397 /* Test source location lookup */
882adb99
MJ
398 subtest_lookup_source_location(bin, func_foo_printf_addr,
399 opt_func_foo_printf_line_no,
400 FUNC_FOO_FILENAME);
6ab5bdaa
AB
401
402 /* Test source location lookup - inlined function */
882adb99
MJ
403 subtest_lookup_source_location(bin, func_foo_tp_addr,
404 opt_func_foo_tp_line_no,
405 FUNC_FOO_FILENAME);
6ab5bdaa 406
d5ddf820 407 bin_info_destroy(bin);
1e638f98 408 bt_fd_cache_fini(&fdc);
6a284733
MJ
409 g_free(data_dir);
410 g_free(bin_path);
6ab5bdaa
AB
411}
412
413int main(int argc, char **argv)
414{
415 int ret;
882adb99
MJ
416 GError *error = NULL;
417 GOptionContext *context;
6ab5bdaa 418
882adb99
MJ
419 context = g_option_context_new("- bin info test");
420 g_option_context_add_main_entries(context, entries, NULL);
421 if (!g_option_context_parse(context, &argc, &argv, &error)) {
422 fprintf(stderr, "option parsing failed: %s\n", error->message);
423 exit(EXIT_FAILURE);
424 }
6ab5bdaa 425
882adb99
MJ
426 g_snprintf(func_foo_printf_name, FUNC_FOO_NAME_LEN,
427 FUNC_FOO_PRINTF_NAME_FMT, opt_func_foo_printf_offset);
428 func_foo_printf_addr =
429 SO_LOW_ADDR + opt_func_foo_addr + opt_func_foo_printf_offset;
430 func_foo_tp_addr =
431 SO_LOW_ADDR + opt_func_foo_addr + opt_func_foo_tp_offset;
432
433 if (build_id_to_bin()) {
434 fprintf(stderr, "Failed to parse / missing build id\n");
435 exit(EXIT_FAILURE);
6ab5bdaa
AB
436 }
437
882adb99
MJ
438 plan_tests(NR_TESTS);
439
91bc8451 440 ret = bin_info_init(BT_LOG_OUTPUT_LEVEL, NULL);
4caab45b 441 ok(ret == 0, "bin_info_init successful");
6ab5bdaa 442
d5ddf820 443 test_bin_info_elf(opt_debug_info_dir);
882adb99 444 test_bin_info_bundled(opt_debug_info_dir);
d5ddf820
AB
445 test_bin_info_build_id(opt_debug_info_dir);
446 test_bin_info_debug_link(opt_debug_info_dir);
6ab5bdaa
AB
447
448 return EXIT_SUCCESS;
449}
This page took 0.067434 seconds and 4 git commands to generate.