1 /*
2 ** sort.c for elfsh
3 **
4 ** Improved by spacewalker to use quicksort
5 ** instead of bubble sort.
6 **
7 ** Started on Wed May 21 15:27:15 2003 mayhem
8 ** Last update Wed May 21 15:31:57 2003 mayhem
9 */
10 #include "libelfsh.h"
11
12
13 /* functions called by qsort() */
sizesort_compare(const Elf32_Sym * p,const Elf32_Sym * q)14 int sizesort_compare(const Elf32_Sym * p, const Elf32_Sym * q)
15 {
16 if (p->st_size < q->st_size)
17 return -1;
18 if (p->st_size > q->st_size)
19 return 1;
20 return 0;
21 }
22
addrsort_compare(const Elf32_Sym * p,const Elf32_Sym * q)23 int addrsort_compare(const Elf32_Sym * p,const Elf32_Sym * q)
24 {
25 if (p->st_value < q->st_value)
26 return -1;
27 if (p->st_value > q->st_value)
28 return 1;
29 return 0;
30 }
31
32 /* Sort the symtab given in parameter */
elfsh_sort_symtab(Elf32_Sym * symtab,int size,int type)33 int elfsh_sort_symtab(Elf32_Sym *symtab, int size, int type)
34 {
35
36 /* Sanity checks */
37 if (symtab == NULL || !size)
38 ELFSH_SETERROR("[libelfsh:sort_symtab] Invalid NULL parameter\n", -1);
39
40 switch (type)
41 {
42 /* Sort by size */
43 case (ELFSH_SORT_BY_SIZE):
44 qsort(symtab, size, sizeof(Elf32_Sym), (void *) sizesort_compare);
45 break;
46 /* Sort by address */
47 case (ELFSH_SORT_BY_ADDR):
48 qsort(symtab, size, sizeof(Elf32_Sym), (void *)addrsort_compare);
49 break;
50 default:
51 /* Unknown sort mode */
52 ELFSH_SETERROR("[libelfsh:sort_symtab] Unknown sorting mode\n",
53 -1);
54 }
55 return (0);
56 }
57
58
59
60 /* Synchronize sorted instance of tables */
elfsh_sync_sorted_symtab(elfshsect_t * sect)61 int elfsh_sync_sorted_symtab(elfshsect_t *sect)
62 {
63 u_int nbr;
64
65 if (sect == NULL || sect->shdr == NULL)
66 ELFSH_SETERROR("[libelfsh:sync_sorted_symtab] Invalid NULL parameter\n",
67 -1);
68 if (sect->shdr->sh_type != SHT_SYMTAB && sect->shdr->sh_type != SHT_DYNSYM)
69 ELFSH_SETERROR("[libelfsh:sync_sorted_symtab] Param is not a symtab\n",
70 -1);
71
72 if (sect->altdata != NULL)
73 free(sect->altdata);
74 nbr = sect->shdr->sh_size / sizeof(Elf32_Sym);
75 sect->altdata = elfsh_copy_symtab(sect->data, nbr);
76 elfsh_sort_symtab(sect->altdata, nbr, ELFSH_SORT_BY_ADDR);
77
78 if (sect->terdata != NULL)
79 free(sect->terdata);
80 sect->terdata = elfsh_copy_symtab(sect->data, nbr);
81 elfsh_sort_symtab(sect->terdata, nbr, ELFSH_SORT_BY_SIZE);
82
83 return (0);
84 }
85