1Upstream-Status: Inappropriate [embedded specific]
2
3We run the ldconfig in the cross fashion. make the code bitsize aware so that
4we can cross build ldconfig cache for various architectures.
5
6Richard Purdie <richard.purdie@linuxfoundation.org> 2009/05/19
7Nitin A Kamble <nitin.a.kamble@intel.com> 2009/03/29
8
9Index: ldconfig-native-2.12.1/readelflib.c
10===================================================================
11--- ldconfig-native-2.12.1.orig/readelflib.c
12+++ ldconfig-native-2.12.1/readelflib.c
13@@ -40,39 +40,212 @@ do								\
14
15 /* Returns 0 if everything is ok, != 0 in case of error.  */
16 int
17-process_elf_file (const char *file_name, const char *lib, int *flag,
18+process_elf_file32 (const char *file_name, const char *lib, int *flag,
19 		  unsigned int *osversion, char **soname, void *file_contents,
20 		  size_t file_length)
21 {
22   int i;
23   unsigned int j;
24-  ElfW(Addr) loadaddr;
25+  Elf32_Addr loadaddr;
26   unsigned int dynamic_addr;
27   size_t dynamic_size;
28   char *program_interpreter;
29
30-  ElfW(Ehdr) *elf_header;
31-  ElfW(Phdr) *elf_pheader, *segment;
32-  ElfW(Dyn) *dynamic_segment, *dyn_entry;
33+  Elf32_Ehdr *elf_header;
34+  Elf32_Phdr *elf_pheader, *segment;
35+  Elf32_Dyn *dynamic_segment, *dyn_entry;
36   char *dynamic_strings;
37
38-  elf_header = (ElfW(Ehdr) *) file_contents;
39+  elf_header = (Elf32_Ehdr *) file_contents;
40   *osversion = 0;
41
42-  if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS))
43+  if (elf_header->e_type != ET_DYN)
44     {
45-      if (opt_verbose)
46+      error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
47+	     elf_header->e_type);
48+      return 1;
49+    }
50+
51+  /* Get information from elf program header.  */
52+  elf_pheader = (Elf32_Phdr *) (elf_header->e_phoff + file_contents);
53+  check_ptr (elf_pheader);
54+
55+  /* The library is an elf library, now search for soname and
56+     libc5/libc6.  */
57+  *flag = FLAG_ELF;
58+
59+  loadaddr = -1;
60+  dynamic_addr = 0;
61+  dynamic_size = 0;
62+  program_interpreter = NULL;
63+  for (i = 0, segment = elf_pheader;
64+       i < elf_header->e_phnum; i++, segment++)
65+    {
66+      check_ptr (segment);
67+
68+      switch (segment->p_type)
69 	{
70-	  if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
71-	    error (0, 0, _("%s is a 32 bit ELF file.\n"), file_name);
72-	  else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64)
73-	    error (0, 0, _("%s is a 64 bit ELF file.\n"), file_name);
74-	  else
75-	    error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name);
76+	case PT_LOAD:
77+	  if (loadaddr == (Elf32_Addr) -1)
78+	    loadaddr = segment->p_vaddr - segment->p_offset;
79+	  break;
80+
81+	case PT_DYNAMIC:
82+	  if (dynamic_addr)
83+	    error (0, 0, _("more than one dynamic segment\n"));
84+
85+	  dynamic_addr = segment->p_offset;
86+	  dynamic_size = segment->p_filesz;
87+	  break;
88+
89+	case PT_INTERP:
90+	  program_interpreter = (char *) (file_contents + segment->p_offset);
91+	  check_ptr (program_interpreter);
92+
93+	  /* Check if this is enough to classify the binary.  */
94+	  for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]);
95+	       ++j)
96+	    if (strcmp (program_interpreter, interpreters[j].soname) == 0)
97+	      {
98+		*flag = interpreters[j].flag;
99+		break;
100+	      }
101+	  break;
102+
103+	case PT_NOTE:
104+	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
105+	    {
106+	      Elf32_Word *abi_note = (Elf32_Word *) (file_contents
107+						     + segment->p_offset);
108+	      Elf32_Addr size = segment->p_filesz;
109+
110+	      while (abi_note [0] != 4 || abi_note [1] != 16
111+		     || abi_note [2] != 1
112+		     || memcmp (abi_note + 3, "GNU", 4) != 0)
113+		{
114+#define ROUND(len) (((len) + sizeof (Elf32_Word)) - 1) & -sizeof (Elf32_Word)))
115+		  Elf32_Addr) note_size = 3 * sizeof (Elf32_Word))
116+					 + ROUND (abi_note[0])
117+					 + ROUND (abi_note[1]);
118+
119+		  if (size - 32 < note_size || note_size == 0)
120+		    {
121+		      size = 0;
122+		      break;
123+		    }
124+		  size -= note_size;
125+		  abi_note = (void *) abi_note + note_size;
126+		}
127+
128+	      if (size == 0)
129+		break;
130+
131+	      *osversion = (abi_note [4] << 24) |
132+			   ((abi_note [5] & 0xff) << 16) |
133+			   ((abi_note [6] & 0xff) << 8) |
134+			   (abi_note [7] & 0xff);
135+	    }
136+	  break;
137+
138+	default:
139+	  break;
140+	}
141+
142+    }
143+  if (loadaddr == (Elf32_Addr) -1)
144+    {
145+      /* Very strange. */
146+      loadaddr = 0;
147+    }
148+
149+  /* Now we can read the dynamic sections.  */
150+  if (dynamic_size == 0)
151+    return 1;
152+
153+  dynamic_segment = (Elf32_Dyn *) (file_contents + dynamic_addr);
154+  check_ptr (dynamic_segment);
155+
156+  /* Find the string table.  */
157+  dynamic_strings = NULL;
158+  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
159+       ++dyn_entry)
160+    {
161+      check_ptr (dyn_entry);
162+      if (dyn_entry->d_tag == DT_STRTAB)
163+	{
164+	  dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
165+	  check_ptr (dynamic_strings);
166+	  break;
167 	}
168-      return 1;
169     }
170
171+  if (dynamic_strings == NULL)
172+    return 1;
173+
174+  /* Now read the DT_NEEDED and DT_SONAME entries.  */
175+  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
176+       ++dyn_entry)
177+    {
178+      if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
179+	{
180+	  char *name = dynamic_strings + dyn_entry->d_un.d_val;
181+	  check_ptr (name);
182+
183+	  if (dyn_entry->d_tag == DT_NEEDED)
184+	    {
185+
186+	      if (*flag == FLAG_ELF)
187+		{
188+		  /* Check if this is enough to classify the binary.  */
189+		  for (j = 0;
190+		       j < sizeof (known_libs) / sizeof (known_libs [0]);
191+		       ++j)
192+		    if (strcmp (name, known_libs [j].soname) == 0)
193+		      {
194+			*flag = known_libs [j].flag;
195+			break;
196+		      }
197+		}
198+	    }
199+
200+	  else if (dyn_entry->d_tag == DT_SONAME)
201+	    *soname = xstrdup (name);
202+
203+	  /* Do we have everything we need?  */
204+	  if (*soname && *flag != FLAG_ELF)
205+	    return 0;
206+	}
207+    }
208+
209+  /* We reach this point only if the file doesn't contain a DT_SONAME
210+     or if we can't classify the library.  If it doesn't have a
211+     soname, return the name of the library.  */
212+  if (*soname == NULL)
213+    *soname = xstrdup (lib);
214+
215+  return 0;
216+}
217+
218+int
219+process_elf_file64 (const char *file_name, const char *lib, int *flag,
220+		  unsigned int *osversion, char **soname, void *file_contents,
221+		  size_t file_length)
222+{
223+  int i;
224+  unsigned int j;
225+  Elf64_Addr loadaddr;
226+  unsigned int dynamic_addr;
227+  size_t dynamic_size;
228+  char *program_interpreter;
229+
230+  Elf64_Ehdr *elf_header;
231+  Elf64_Phdr *elf_pheader, *segment;
232+  Elf64_Dyn *dynamic_segment, *dyn_entry;
233+  char *dynamic_strings;
234+
235+  elf_header = (Elf64_Ehdr *) file_contents;
236+  *osversion = 0;
237+
238   if (elf_header->e_type != ET_DYN)
239     {
240       error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
241@@ -81,7 +254,7 @@ process_elf_file (const char *file_name,
242     }
243
244   /* Get information from elf program header.  */
245-  elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents);
246+  elf_pheader = (Elf64_Phdr *) (elf_header->e_phoff + file_contents);
247   check_ptr (elf_pheader);
248
249   /* The library is an elf library, now search for soname and
250@@ -100,7 +273,7 @@ process_elf_file (const char *file_name,
251       switch (segment->p_type)
252 	{
253 	case PT_LOAD:
254-	  if (loadaddr == (ElfW(Addr)) -1)
255+	  if (loadaddr == (Elf64_Addr) -1)
256 	    loadaddr = segment->p_vaddr - segment->p_offset;
257 	  break;
258
259@@ -129,16 +302,16 @@ process_elf_file (const char *file_name,
260 	case PT_NOTE:
261 	  if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
262 	    {
263-	      ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents
264+	      Elf64_Word *abi_note = (Elf64_Word *) (file_contents
265 						     + segment->p_offset);
266-	      ElfW(Addr) size = segment->p_filesz;
267+	      Elf64_Addr size = segment->p_filesz;
268
269 	      while (abi_note [0] != 4 || abi_note [1] != 16
270 		     || abi_note [2] != 1
271 		     || memcmp (abi_note + 3, "GNU", 4) != 0)
272 		{
273-#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
274-		  ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
275+#define ROUND(len) (((len) + sizeof (Elf64_Word) - 1) & -sizeof (Elf64_Word))
276+		  Elf64_Addr note_size = 3 * sizeof (Elf64_Word)
277 					 + ROUND (abi_note[0])
278 					 + ROUND (abi_note[1]);
279
280@@ -166,7 +339,7 @@ process_elf_file (const char *file_name,
281 	}
282
283     }
284-  if (loadaddr == (ElfW(Addr)) -1)
285+  if (loadaddr == (Elf64_Addr) -1)
286     {
287       /* Very strange. */
288       loadaddr = 0;
289@@ -176,7 +349,7 @@ process_elf_file (const char *file_name,
290   if (dynamic_size == 0)
291     return 1;
292
293-  dynamic_segment = (ElfW(Dyn) *) (file_contents + dynamic_addr);
294+  dynamic_segment = (Elf64_Dyn *) (file_contents + dynamic_addr);
295   check_ptr (dynamic_segment);
296
297   /* Find the string table.  */
298@@ -233,3 +406,33 @@ process_elf_file (const char *file_name,
299
300   return 0;
301 }
302+/* Returns 0 if everything is ok, != 0 in case of error.  */
303+int
304+process_elf_file (const char *file_name, const char *lib, int *flag,
305+		  unsigned int *osversion, char **soname, void *file_contents,
306+		  size_t file_length)
307+{
308+  int i;
309+  unsigned int j;
310+  ElfW(Addr) loadaddr;
311+  unsigned int dynamic_addr;
312+  size_t dynamic_size;
313+  char *program_interpreter;
314+
315+  ElfW(Ehdr) *elf_header;
316+  ElfW(Phdr) *elf_pheader, *segment;
317+  ElfW(Dyn) *dynamic_segment, *dyn_entry;
318+  char *dynamic_strings;
319+
320+  elf_header = (ElfW(Ehdr) *) file_contents;
321+  *osversion = 0;
322+
323+  if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
324+    return process_elf_file32(file_name, lib,flag, osversion, soname, file_contents, file_length);
325+  else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64)
326+    return process_elf_file64(file_name, lib,flag, osversion, soname, file_contents, file_length);
327+  error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name);
328+  return 1;
329+}
330+
331+
332