summaryrefslogtreecommitdiffstats
path: root/tools/objtool/elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/objtool/elf.c')
-rw-r--r--tools/objtool/elf.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 6e9f980a7d26..c1c338661699 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include "elf.h"
#include "warn.h"
@@ -175,19 +176,20 @@ static int read_sections(struct elf *elf)
return -1;
}
- sec->data = elf_getdata(s, NULL);
- if (!sec->data) {
- WARN_ELF("elf_getdata");
- return -1;
- }
-
- if (sec->data->d_off != 0 ||
- sec->data->d_size != sec->sh.sh_size) {
- WARN("unexpected data attributes for %s", sec->name);
- return -1;
+ if (sec->sh.sh_size != 0) {
+ sec->data = elf_getdata(s, NULL);
+ if (!sec->data) {
+ WARN_ELF("elf_getdata");
+ return -1;
+ }
+ if (sec->data->d_off != 0 ||
+ sec->data->d_size != sec->sh.sh_size) {
+ WARN("unexpected data attributes for %s",
+ sec->name);
+ return -1;
+ }
}
-
- sec->len = sec->data->d_size;
+ sec->len = sec->sh.sh_size;
}
/* sanity check, one more call to elf_nextscn() should return NULL */
@@ -357,7 +359,8 @@ struct elf *elf_open(const char *name, int flags)
elf->fd = open(name, flags);
if (elf->fd == -1) {
- perror("open");
+ fprintf(stderr, "objtool: Can't open '%s': %s\n",
+ name, strerror(errno));
goto err;
}
@@ -508,6 +511,7 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
strcat(relaname, base->name);
sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
+ free(relaname);
if (!sec)
return NULL;
@@ -561,6 +565,7 @@ int elf_write(struct elf *elf)
struct section *sec;
Elf_Scn *s;
+ /* Update section headers for changed sections: */
list_for_each_entry(sec, &elf->sections, list) {
if (sec->changed) {
s = elf_getscn(elf->elf, sec->idx);
@@ -568,13 +573,17 @@ int elf_write(struct elf *elf)
WARN_ELF("elf_getscn");
return -1;
}
- if (!gelf_update_shdr (s, &sec->sh)) {
+ if (!gelf_update_shdr(s, &sec->sh)) {
WARN_ELF("gelf_update_shdr");
return -1;
}
}
}
+ /* Make sure the new section header entries get updated properly. */
+ elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY);
+
+ /* Write all changes to the file. */
if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
WARN_ELF("elf_update");
return -1;
OpenPOWER on IntegriCloud