elf.c 16.6 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * elf.c - ELF access library
 *
 * Adapted from kpatch (https://github.com/dynup/kpatch):
 * Copyright (C) 2013-2015 Josh Poimboeuf <jpoimboe@redhat.com>
 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
17
#include <errno.h>
P
Peter Zijlstra 已提交
18
#include "builtin.h"
19 20 21 22

#include "elf.h"
#include "warn.h"

23 24
#define MAX_NAME_LEN 128

25 26 27 28 29
static inline u32 str_hash(const char *str)
{
	return jhash(str, strlen(str), 0);
}

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
static void rb_add(struct rb_root *tree, struct rb_node *node,
		   int (*cmp)(struct rb_node *, const struct rb_node *))
{
	struct rb_node **link = &tree->rb_node;
	struct rb_node *parent = NULL;

	while (*link) {
		parent = *link;
		if (cmp(node, parent) < 0)
			link = &parent->rb_left;
		else
			link = &parent->rb_right;
	}

	rb_link_node(node, parent, link);
	rb_insert_color(node, tree);
}

static struct rb_node *rb_find_first(struct rb_root *tree, const void *key,
			       int (*cmp)(const void *key, const struct rb_node *))
{
	struct rb_node *node = tree->rb_node;
	struct rb_node *match = NULL;

	while (node) {
		int c = cmp(key, node);
		if (c <= 0) {
			if (!c)
				match = node;
			node = node->rb_left;
		} else if (c > 0) {
			node = node->rb_right;
		}
	}

	return match;
}

static struct rb_node *rb_next_match(struct rb_node *node, const void *key,
				    int (*cmp)(const void *key, const struct rb_node *))
{
	node = rb_next(node);
	if (node && cmp(key, node))
		node = NULL;
	return node;
}

#define rb_for_each(tree, node, key, cmp) \
	for ((node) = rb_find_first((tree), (key), (cmp)); \
	     (node); (node) = rb_next_match((node), (key), (cmp)))

static int symbol_to_offset(struct rb_node *a, const struct rb_node *b)
{
	struct symbol *sa = rb_entry(a, struct symbol, node);
	struct symbol *sb = rb_entry(b, struct symbol, node);

	if (sa->offset < sb->offset)
		return -1;
	if (sa->offset > sb->offset)
		return 1;

	if (sa->len < sb->len)
		return -1;
	if (sa->len > sb->len)
		return 1;

	sa->alias = sb;

	return 0;
}

static int symbol_by_offset(const void *key, const struct rb_node *node)
{
	const struct symbol *s = rb_entry(node, struct symbol, node);
	const unsigned long *o = key;

	if (*o < s->offset)
		return -1;
108
	if (*o >= s->offset + s->len)
109 110 111 112 113
		return 1;

	return 0;
}

114 115 116 117
struct section *find_section_by_name(struct elf *elf, const char *name)
{
	struct section *sec;

118
	hash_for_each_possible(elf->section_name_hash, sec, name_hash, str_hash(name))
119 120 121 122 123 124 125 126 127 128 129
		if (!strcmp(sec->name, name))
			return sec;

	return NULL;
}

static struct section *find_section_by_index(struct elf *elf,
					     unsigned int idx)
{
	struct section *sec;

130
	hash_for_each_possible(elf->section_hash, sec, hash, idx)
131 132 133 134 135 136 137 138 139 140
		if (sec->idx == idx)
			return sec;

	return NULL;
}

static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx)
{
	struct symbol *sym;

141 142 143
	hash_for_each_possible(elf->symbol_hash, sym, hash, idx)
		if (sym->idx == idx)
			return sym;
144 145 146 147 148 149

	return NULL;
}

struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
{
150
	struct rb_node *node;
151

152 153 154 155 156 157
	rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) {
		struct symbol *s = rb_entry(node, struct symbol, node);

		if (s->offset == offset && s->type != STT_SECTION)
			return s;
	}
158 159 160 161 162 163

	return NULL;
}

struct symbol *find_func_by_offset(struct section *sec, unsigned long offset)
{
164
	struct rb_node *node;
165

166 167 168 169 170 171
	rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) {
		struct symbol *s = rb_entry(node, struct symbol, node);

		if (s->offset == offset && s->type == STT_FUNC)
			return s;
	}
172 173 174 175

	return NULL;
}

176
struct symbol *find_symbol_containing(struct section *sec, unsigned long offset)
177
{
178
	struct rb_node *node;
179

180 181 182 183 184 185
	rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) {
		struct symbol *s = rb_entry(node, struct symbol, node);

		if (s->type != STT_SECTION)
			return s;
	}
186 187 188 189

	return NULL;
}

190
struct symbol *find_func_containing(struct section *sec, unsigned long offset)
191 192 193 194 195 196 197 198 199 200 201 202 203 204
{
	struct rb_node *node;

	rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) {
		struct symbol *s = rb_entry(node, struct symbol, node);

		if (s->type == STT_FUNC)
			return s;
	}

	return NULL;
}

struct symbol *find_symbol_by_name(struct elf *elf, const char *name)
205 206 207
{
	struct symbol *sym;

208 209 210
	hash_for_each_possible(elf->symbol_name_hash, sym, name_hash, str_hash(name))
		if (!strcmp(sym->name, name))
			return sym;
211 212 213 214

	return NULL;
}

215 216
struct rela *find_rela_by_dest_range(struct elf *elf, struct section *sec,
				     unsigned long offset, unsigned int len)
217
{
218
	struct rela *rela, *r = NULL;
219
	unsigned long o;
220 221 222 223

	if (!sec->rela)
		return NULL;

224 225
	sec = sec->rela;

226
	for_offset_range(o, offset, offset + len) {
227 228
		hash_for_each_possible(elf->rela_hash, rela, hash,
				       sec_offset_hash(sec, o)) {
229 230 231 232 233 234 235
			if (rela->sec != sec)
				continue;

			if (rela->offset >= offset && rela->offset < offset + len) {
				if (!r || rela->offset < r->offset)
					r = rela;
			}
236
		}
237 238
		if (r)
			return r;
239
	}
240 241 242 243

	return NULL;
}

244
struct rela *find_rela_by_dest(struct elf *elf, struct section *sec, unsigned long offset)
245
{
246
	return find_rela_by_dest_range(elf, sec, offset, 1);
247 248 249 250 251 252 253 254 255 256
}

static int read_sections(struct elf *elf)
{
	Elf_Scn *s = NULL;
	struct section *sec;
	size_t shstrndx, sections_nr;
	int i;

	if (elf_getshdrnum(elf->elf, &sections_nr)) {
257
		WARN_ELF("elf_getshdrnum");
258 259 260 261
		return -1;
	}

	if (elf_getshdrstrndx(elf->elf, &shstrndx)) {
262
		WARN_ELF("elf_getshdrstrndx");
263 264 265 266 267 268 269 270 271 272 273
		return -1;
	}

	for (i = 0; i < sections_nr; i++) {
		sec = malloc(sizeof(*sec));
		if (!sec) {
			perror("malloc");
			return -1;
		}
		memset(sec, 0, sizeof(*sec));

274 275
		INIT_LIST_HEAD(&sec->symbol_list);
		INIT_LIST_HEAD(&sec->rela_list);
276 277 278

		s = elf_getscn(elf->elf, i);
		if (!s) {
279
			WARN_ELF("elf_getscn");
280 281 282 283 284 285
			return -1;
		}

		sec->idx = elf_ndxscn(s);

		if (!gelf_getshdr(s, &sec->sh)) {
286
			WARN_ELF("gelf_getshdr");
287 288 289 290 291
			return -1;
		}

		sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name);
		if (!sec->name) {
292
			WARN_ELF("elf_strptr");
293 294 295
			return -1;
		}

296 297 298 299 300 301 302 303 304 305 306 307
		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;
			}
308
		}
309
		sec->len = sec->sh.sh_size;
310 311 312

		list_add_tail(&sec->list, &elf->sections);
		hash_add(elf->section_hash, &sec->hash, sec->idx);
313
		hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
314 315
	}

P
Peter Zijlstra 已提交
316 317 318
	if (stats)
		printf("nr_sections: %lu\n", (unsigned long)sections_nr);

319 320 321 322 323 324 325 326 327 328 329
	/* sanity check, one more call to elf_nextscn() should return NULL */
	if (elf_nextscn(elf->elf, s)) {
		WARN("section entry mismatch");
		return -1;
	}

	return 0;
}

static int read_symbols(struct elf *elf)
{
330
	struct section *symtab, *sec;
331 332 333
	struct symbol *sym, *pfunc;
	struct list_head *entry;
	struct rb_node *pnode;
334
	int symbols_nr, i;
335
	char *coldstr;
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351

	symtab = find_section_by_name(elf, ".symtab");
	if (!symtab) {
		WARN("missing symbol table");
		return -1;
	}

	symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize;

	for (i = 0; i < symbols_nr; i++) {
		sym = malloc(sizeof(*sym));
		if (!sym) {
			perror("malloc");
			return -1;
		}
		memset(sym, 0, sizeof(*sym));
352
		sym->alias = sym;
353 354 355

		sym->idx = i;

356 357
		if (!gelf_getsym(symtab->data, i, &sym->sym)) {
			WARN_ELF("gelf_getsym");
358 359 360 361 362 363
			goto err;
		}

		sym->name = elf_strptr(elf->elf, symtab->sh.sh_link,
				       sym->sym.st_name);
		if (!sym->name) {
364
			WARN_ELF("elf_strptr");
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
			goto err;
		}

		sym->type = GELF_ST_TYPE(sym->sym.st_info);
		sym->bind = GELF_ST_BIND(sym->sym.st_info);

		if (sym->sym.st_shndx > SHN_UNDEF &&
		    sym->sym.st_shndx < SHN_LORESERVE) {
			sym->sec = find_section_by_index(elf,
							 sym->sym.st_shndx);
			if (!sym->sec) {
				WARN("couldn't find section for symbol %s",
				     sym->name);
				goto err;
			}
			if (sym->type == STT_SECTION) {
				sym->name = sym->sec->name;
				sym->sec->sym = sym;
			}
		} else
			sym->sec = find_section_by_index(elf, 0);

		sym->offset = sym->sym.st_value;
		sym->len = sym->sym.st_size;

390 391 392 393 394 395
		rb_add(&sym->sec->symbol_tree, &sym->node, symbol_to_offset);
		pnode = rb_prev(&sym->node);
		if (pnode)
			entry = &rb_entry(pnode, struct symbol, node)->list;
		else
			entry = &sym->sec->symbol_list;
396
		list_add(&sym->list, entry);
397
		hash_add(elf->symbol_hash, &sym->hash, sym->idx);
398
		hash_add(elf->symbol_name_hash, &sym->name_hash, str_hash(sym->name));
399 400
	}

P
Peter Zijlstra 已提交
401 402 403
	if (stats)
		printf("nr_symbols: %lu\n", (unsigned long)symbols_nr);

404 405 406
	/* Create parent/child links for any cold subfunctions */
	list_for_each_entry(sec, &elf->sections, list) {
		list_for_each_entry(sym, &sec->symbol_list, list) {
407 408
			char pname[MAX_NAME_LEN + 1];
			size_t pnamelen;
409 410 411
			if (sym->type != STT_FUNC)
				continue;
			sym->pfunc = sym->cfunc = sym;
412
			coldstr = strstr(sym->name, ".cold");
413 414 415
			if (!coldstr)
				continue;

416 417 418 419 420 421 422 423 424 425
			pnamelen = coldstr - sym->name;
			if (pnamelen > MAX_NAME_LEN) {
				WARN("%s(): parent function name exceeds maximum length of %d characters",
				     sym->name, MAX_NAME_LEN);
				return -1;
			}

			strncpy(pname, sym->name, pnamelen);
			pname[pnamelen] = '\0';
			pfunc = find_symbol_by_name(elf, pname);
426 427 428 429

			if (!pfunc) {
				WARN("%s(): can't find parent function",
				     sym->name);
430
				return -1;
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
			}

			sym->pfunc = pfunc;
			pfunc->cfunc = sym;

			/*
			 * Unfortunately, -fnoreorder-functions puts the child
			 * inside the parent.  Remove the overlap so we can
			 * have sane assumptions.
			 *
			 * Note that pfunc->len now no longer matches
			 * pfunc->sym.st_size.
			 */
			if (sym->sec == pfunc->sec &&
			    sym->offset >= pfunc->offset &&
			    sym->offset + sym->len == pfunc->offset + pfunc->len) {
				pfunc->len -= sym->len;
448 449 450 451
			}
		}
	}

452 453 454 455 456 457 458 459 460 461 462 463 464
	return 0;

err:
	free(sym);
	return -1;
}

static int read_relas(struct elf *elf)
{
	struct section *sec;
	struct rela *rela;
	int i;
	unsigned int symndx;
P
Peter Zijlstra 已提交
465
	unsigned long nr_rela, max_rela = 0, tot_rela = 0;
466 467 468 469 470 471 472 473 474 475 476 477 478 479

	list_for_each_entry(sec, &elf->sections, list) {
		if (sec->sh.sh_type != SHT_RELA)
			continue;

		sec->base = find_section_by_name(elf, sec->name + 5);
		if (!sec->base) {
			WARN("can't find base section for rela section %s",
			     sec->name);
			return -1;
		}

		sec->base->rela = sec;

P
Peter Zijlstra 已提交
480
		nr_rela = 0;
481 482 483 484 485 486 487 488
		for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
			rela = malloc(sizeof(*rela));
			if (!rela) {
				perror("malloc");
				return -1;
			}
			memset(rela, 0, sizeof(*rela));

489 490
			if (!gelf_getrela(sec->data, i, &rela->rela)) {
				WARN_ELF("gelf_getrela");
491 492 493 494 495 496 497 498
				return -1;
			}

			rela->type = GELF_R_TYPE(rela->rela.r_info);
			rela->addend = rela->rela.r_addend;
			rela->offset = rela->rela.r_offset;
			symndx = GELF_R_SYM(rela->rela.r_info);
			rela->sym = find_symbol_by_index(elf, symndx);
499
			rela->sec = sec;
500 501 502 503 504
			if (!rela->sym) {
				WARN("can't find rela entry symbol %d for %s",
				     symndx, sec->name);
				return -1;
			}
505 506

			list_add_tail(&rela->list, &sec->rela_list);
507
			hash_add(elf->rela_hash, &rela->hash, rela_hash(rela));
P
Peter Zijlstra 已提交
508
			nr_rela++;
509
		}
P
Peter Zijlstra 已提交
510 511 512 513 514 515 516
		max_rela = max(max_rela, nr_rela);
		tot_rela += nr_rela;
	}

	if (stats) {
		printf("max_rela: %lu\n", max_rela);
		printf("tot_rela: %lu\n", tot_rela);
517 518 519 520 521
	}

	return 0;
}

522
struct elf *elf_read(const char *name, int flags)
523 524
{
	struct elf *elf;
525
	Elf_Cmd cmd;
526 527 528 529 530 531 532 533 534 535

	elf_version(EV_CURRENT);

	elf = malloc(sizeof(*elf));
	if (!elf) {
		perror("malloc");
		return NULL;
	}
	memset(elf, 0, sizeof(*elf));

536
	hash_init(elf->symbol_hash);
537
	hash_init(elf->symbol_name_hash);
538
	hash_init(elf->section_hash);
539
	hash_init(elf->section_name_hash);
540
	hash_init(elf->rela_hash);
541 542
	INIT_LIST_HEAD(&elf->sections);

543
	elf->fd = open(name, flags);
544
	if (elf->fd == -1) {
545 546
		fprintf(stderr, "objtool: Can't open '%s': %s\n",
			name, strerror(errno));
547 548 549
		goto err;
	}

550 551 552 553 554 555 556 557
	if ((flags & O_ACCMODE) == O_RDONLY)
		cmd = ELF_C_READ_MMAP;
	else if ((flags & O_ACCMODE) == O_RDWR)
		cmd = ELF_C_RDWR;
	else /* O_WRONLY */
		cmd = ELF_C_WRITE;

	elf->elf = elf_begin(elf->fd, cmd, NULL);
558
	if (!elf->elf) {
559
		WARN_ELF("elf_begin");
560 561 562 563
		goto err;
	}

	if (!gelf_getehdr(elf->elf, &elf->ehdr)) {
564
		WARN_ELF("gelf_getehdr");
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
		goto err;
	}

	if (read_sections(elf))
		goto err;

	if (read_symbols(elf))
		goto err;

	if (read_relas(elf))
		goto err;

	return elf;

err:
	elf_close(elf);
	return NULL;
}

584 585 586 587 588
struct section *elf_create_section(struct elf *elf, const char *name,
				   size_t entsize, int nr)
{
	struct section *sec, *shstrtab;
	size_t size = entsize * nr;
589
	Elf_Scn *s;
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
	Elf_Data *data;

	sec = malloc(sizeof(*sec));
	if (!sec) {
		perror("malloc");
		return NULL;
	}
	memset(sec, 0, sizeof(*sec));

	INIT_LIST_HEAD(&sec->symbol_list);
	INIT_LIST_HEAD(&sec->rela_list);

	s = elf_newscn(elf->elf);
	if (!s) {
		WARN_ELF("elf_newscn");
		return NULL;
	}

	sec->name = strdup(name);
	if (!sec->name) {
		perror("strdup");
		return NULL;
	}

	sec->idx = elf_ndxscn(s);
	sec->len = size;
	sec->changed = true;

	sec->data = elf_newdata(s);
	if (!sec->data) {
		WARN_ELF("elf_newdata");
		return NULL;
	}

	sec->data->d_size = size;
	sec->data->d_align = 1;

	if (size) {
		sec->data->d_buf = malloc(size);
		if (!sec->data->d_buf) {
			perror("malloc");
			return NULL;
		}
		memset(sec->data->d_buf, 0, size);
	}

	if (!gelf_getshdr(s, &sec->sh)) {
		WARN_ELF("gelf_getshdr");
		return NULL;
	}

	sec->sh.sh_size = size;
	sec->sh.sh_entsize = entsize;
	sec->sh.sh_type = SHT_PROGBITS;
	sec->sh.sh_addralign = 1;
	sec->sh.sh_flags = SHF_ALLOC;


648
	/* Add section name to .shstrtab (or .strtab for Clang) */
649
	shstrtab = find_section_by_name(elf, ".shstrtab");
650 651
	if (!shstrtab)
		shstrtab = find_section_by_name(elf, ".strtab");
652
	if (!shstrtab) {
653
		WARN("can't find .shstrtab or .strtab section");
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
		return NULL;
	}

	s = elf_getscn(elf->elf, shstrtab->idx);
	if (!s) {
		WARN_ELF("elf_getscn");
		return NULL;
	}

	data = elf_newdata(s);
	if (!data) {
		WARN_ELF("elf_newdata");
		return NULL;
	}

	data->d_buf = sec->name;
	data->d_size = strlen(name) + 1;
	data->d_align = 1;

	sec->sh.sh_name = shstrtab->len;

	shstrtab->len += strlen(name) + 1;
	shstrtab->changed = true;

678 679
	list_add_tail(&sec->list, &elf->sections);
	hash_add(elf->section_hash, &sec->hash, sec->idx);
680
	hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
681

682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
	return sec;
}

struct section *elf_create_rela_section(struct elf *elf, struct section *base)
{
	char *relaname;
	struct section *sec;

	relaname = malloc(strlen(base->name) + strlen(".rela") + 1);
	if (!relaname) {
		perror("malloc");
		return NULL;
	}
	strcpy(relaname, ".rela");
	strcat(relaname, base->name);

	sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
699
	free(relaname);
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
	if (!sec)
		return NULL;

	base->rela = sec;
	sec->base = base;

	sec->sh.sh_type = SHT_RELA;
	sec->sh.sh_addralign = 8;
	sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
	sec->sh.sh_info = base->idx;
	sec->sh.sh_flags = SHF_INFO_LINK;

	return sec;
}

int elf_rebuild_rela_section(struct section *sec)
{
	struct rela *rela;
	int nr, idx = 0, size;
	GElf_Rela *relas;

	nr = 0;
	list_for_each_entry(rela, &sec->rela_list, list)
		nr++;

	size = nr * sizeof(*relas);
	relas = malloc(size);
	if (!relas) {
		perror("malloc");
		return -1;
	}

	sec->data->d_buf = relas;
	sec->data->d_size = size;

	sec->sh.sh_size = size;

	idx = 0;
	list_for_each_entry(rela, &sec->rela_list, list) {
		relas[idx].r_offset = rela->offset;
		relas[idx].r_addend = rela->addend;
		relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type);
		idx++;
	}

	return 0;
}

int elf_write(struct elf *elf)
{
	struct section *sec;
	Elf_Scn *s;

753
	/* Update section headers for changed sections: */
754 755 756 757 758 759 760
	list_for_each_entry(sec, &elf->sections, list) {
		if (sec->changed) {
			s = elf_getscn(elf->elf, sec->idx);
			if (!s) {
				WARN_ELF("elf_getscn");
				return -1;
			}
761
			if (!gelf_update_shdr(s, &sec->sh)) {
762 763 764 765 766 767
				WARN_ELF("gelf_update_shdr");
				return -1;
			}
		}
	}

768 769 770 771
	/* 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. */
772 773 774 775 776 777 778 779
	if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
		WARN_ELF("elf_update");
		return -1;
	}

	return 0;
}

780 781 782 783 784 785
void elf_close(struct elf *elf)
{
	struct section *sec, *tmpsec;
	struct symbol *sym, *tmpsym;
	struct rela *rela, *tmprela;

786 787 788 789 790 791
	if (elf->elf)
		elf_end(elf->elf);

	if (elf->fd > 0)
		close(elf->fd);

792
	list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) {
793
		list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) {
794
			list_del(&sym->list);
795
			hash_del(&sym->hash);
796 797
			free(sym);
		}
798
		list_for_each_entry_safe(rela, tmprela, &sec->rela_list, list) {
799
			list_del(&rela->list);
800
			hash_del(&rela->hash);
801 802 803 804 805
			free(rela);
		}
		list_del(&sec->list);
		free(sec);
	}
806

807 808
	free(elf);
}