summaryrefslogtreecommitdiff
path: root/tools/perf/util/genelf_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/genelf_debug.c')
-rw-r--r--tools/perf/util/genelf_debug.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c
index 40789d8603d0..8588b3e35e00 100644
--- a/tools/perf/util/genelf_debug.c
+++ b/tools/perf/util/genelf_debug.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* genelf_debug.c
* Copyright (C) 2015, Google, Inc
@@ -5,13 +6,12 @@
* Contributed by:
* Stephane Eranian <eranian@google.com>
*
- * Released under the GPL v2.
- *
* based on GPLv2 source code from Oprofile
* @remark Copyright 2007 OProfile authors
* @author Philippe Elie
*/
#include <linux/compiler.h>
+#include <linux/zalloc.h>
#include <sys/types.h>
#include <stdio.h>
#include <getopt.h>
@@ -25,7 +25,6 @@
#include <err.h>
#include <dwarf.h>
-#include "perf.h"
#include "genelf.h"
#include "../util/jitdump.h"
@@ -89,6 +88,12 @@ buffer_ext_init(struct buffer_ext *be)
be->max_sz = 0;
}
+static void
+buffer_ext_exit(struct buffer_ext *be)
+{
+ zfree(&be->data);
+}
+
static inline size_t
buffer_ext_size(struct buffer_ext *be)
{
@@ -332,6 +337,9 @@ static void emit_lineno_info(struct buffer_ext *be,
{
size_t i;
+ /* as described in the jitdump format */
+ const char repeated_name_marker[] = {'\xff', '\0'};
+
/*
* Machine state at start of a statement program
* address = 0
@@ -344,7 +352,7 @@ static void emit_lineno_info(struct buffer_ext *be,
*/
/* start state of the state machine we take care of */
- unsigned long last_vma = code_addr;
+ unsigned long last_vma = 0;
char const *cur_filename = NULL;
unsigned long cur_file_idx = 0;
int last_line = 1;
@@ -358,7 +366,8 @@ static void emit_lineno_info(struct buffer_ext *be,
/*
* check if filename changed, if so add it
*/
- if (!cur_filename || strcmp(cur_filename, ent->name)) {
+ if ((!cur_filename || strcmp(cur_filename, ent->name)) &&
+ strcmp(repeated_name_marker, ent->name)) {
emit_lne_define_filename(be, ent->name);
cur_filename = ent->name;
emit_set_file(be, ++cur_file_idx);
@@ -475,7 +484,7 @@ jit_process_debug_info(uint64_t code_addr,
ent = debug_entry_next(ent);
}
add_compilation_unit(di, buffer_ext_size(dl));
- add_debug_line(dl, debug, nr_debug_entries, 0);
+ add_debug_line(dl, debug, nr_debug_entries, GEN_ELF_TEXT_OFFSET);
add_debug_abbrev(da);
if (0) buffer_ext_dump(da, "abbrev");
@@ -489,28 +498,28 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
Elf_Scn *scn;
Elf_Shdr *shdr;
struct buffer_ext dl, di, da;
- int ret;
+ int ret = -1;
buffer_ext_init(&dl);
buffer_ext_init(&di);
buffer_ext_init(&da);
- ret = jit_process_debug_info(code_addr, debug, nr_debug_entries, &dl, &da, &di);
- if (ret)
- return -1;
+ if (jit_process_debug_info(code_addr, debug, nr_debug_entries, &dl, &da, &di))
+ goto out;
+
/*
* setup .debug_line section
*/
scn = elf_newscn(e);
if (!scn) {
warnx("cannot create section");
- return -1;
+ goto out;
}
d = elf_newdata(scn);
if (!d) {
warnx("cannot get new data");
- return -1;
+ goto out;
}
d->d_align = 1;
@@ -523,7 +532,7 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
shdr = elf_getshdr(scn);
if (!shdr) {
warnx("cannot get section header");
- return -1;
+ goto out;
}
shdr->sh_name = 52; /* .debug_line */
@@ -538,13 +547,13 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
scn = elf_newscn(e);
if (!scn) {
warnx("cannot create section");
- return -1;
+ goto out;
}
d = elf_newdata(scn);
if (!d) {
warnx("cannot get new data");
- return -1;
+ goto out;
}
d->d_align = 1;
@@ -557,7 +566,7 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
shdr = elf_getshdr(scn);
if (!shdr) {
warnx("cannot get section header");
- return -1;
+ goto out;
}
shdr->sh_name = 64; /* .debug_info */
@@ -572,13 +581,13 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
scn = elf_newscn(e);
if (!scn) {
warnx("cannot create section");
- return -1;
+ goto out;
}
d = elf_newdata(scn);
if (!d) {
warnx("cannot get new data");
- return -1;
+ goto out;
}
d->d_align = 1;
@@ -591,7 +600,7 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
shdr = elf_getshdr(scn);
if (!shdr) {
warnx("cannot get section header");
- return -1;
+ goto out;
}
shdr->sh_name = 76; /* .debug_info */
@@ -603,9 +612,14 @@ jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries
/*
* now we update the ELF image with all the sections
*/
- if (elf_update(e, ELF_C_WRITE) < 0) {
+ if (elf_update(e, ELF_C_WRITE) < 0)
warnx("elf_update debug failed");
- return -1;
- }
- return 0;
+ else
+ ret = 0;
+
+out:
+ buffer_ext_exit(&dl);
+ buffer_ext_exit(&di);
+ buffer_ext_exit(&da);
+ return ret;
}