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