18 #include "hook-arch-c.h"
21 /* Make the checksumming faster but core file specific by mincore(2)?
22 For some important swapped out libraries the checksum would get void. */
25 static ElfW(LibobjidHdr) *header;
26 static size_t pages_size;
27 static unsigned obj_allocated;
28 static ElfW(LibobjidObj) *obj;
31 static void header_update (void)
33 obj_allocated = (pages_size - offsetof (ElfW(LibobjidHdr), obj)) / sizeof (header->obj[0]);
34 assert (obj_allocated >= header->obj_count);
37 static int header_init (void)
39 pages_size = PAGE_SIZE;
40 header = mmap (NULL, pages_size, PROT_READ | PROT_WRITE,
41 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
42 if (header == MAP_FAILED)
45 fprintf (stderr, "libobjid: Failed to map %lu bytes: %m\n",
46 (unsigned long) pages_size);
49 header->obj_count = 0;
55 static int header_resize (size_t pages_size_new)
57 ElfW(LibobjidHdr) *header_new;
59 pages_size_new = (pages_size_new + PAGE_SIZE - 1) & PAGE_MASK;
61 header_new = mremap (header, pages_size, pages_size_new, MREMAP_MAYMOVE);
62 if (header_new == MAP_FAILED)
65 fprintf (stderr, "libobjid: Failed to remap %lu to %lu bytes: %m\n",
66 (unsigned long) pages_size, (unsigned long) pages_size_new);
71 pages_size = pages_size_new;
77 static void header_finish (void)
79 size_t strings_size = 0;
83 for (obji = 0; obji < header->obj_count; obji++)
84 strings_size += strlen ((const char *) header->obj[obji].filename) + 1;
86 header->size = sizeof (*header) + header->obj_count * sizeof (*header->obj)
88 /* Possibly even shrink the allocated pages. */
89 header_resize (header->size);
91 /* Do not reuse any address above, header_resize() could move it. */
92 string_ptr = (char *) header + sizeof (*header)
93 + header->obj_count * sizeof (*header->obj);
95 for (obji = 0; obji < header->obj_count; obji++)
97 const char *filename_orig = (const char *) header->obj[obji].filename;
99 strcpy (string_ptr, filename_orig);
100 header->obj[obji].filename = (ElfW (Addr)) string_ptr;
101 string_ptr += strlen (filename_orig) + 1;
103 assert (string_ptr == (char *) header + header->size);
105 header->magic = ElfW(Magic);
106 header->self = (ElfW(Addr)) header;
107 header->self_not = ~(ElfW(Addr)) header;
110 /* Returns non-zero on error. */
111 static int checksum_open (const char *filename)
113 assert (header != NULL);
115 if (header->obj_count == obj_allocated)
117 assert (pages_size >= 1);
118 if (header_resize (pages_size * 2))
120 assert (header->obj_count < obj_allocated);
123 obj = &header->obj[header->obj_count];
125 /* It should not happen but avoid the array termination. */
126 if (filename == NULL)
129 obj->filename = (ElfW(Addr)) filename;
132 fprintf (stderr, "%s\n", filename);
137 static void checksum_data (ElfW(Word) *sum, void *start, void *end)
141 for (ptr = start; (void *) ptr < end; ptr++)
142 *sum = *sum * 31 + *ptr;
145 fprintf (stderr, "\t%p - %p (0x%lx)\n", start, end, (unsigned long) *sum);
148 static void checksum_close (void)
152 assert (header->obj_count <= obj_allocated);
155 /* Range is provided only for debug purposes. */
156 static void checksum_cancel (void *start, void *end)
159 fprintf (stderr, "\tCANCEL: %p - %p\n", start, end);
162 static int phdr_callback (struct dl_phdr_info *info, size_t size, void *data)
167 for (j = 0; j < info->dlpi_phnum; j++)
171 if (info->dlpi_phdr[j].p_type != PT_LOAD)
173 if (!(info->dlpi_phdr[j].p_flags & PF_R))
175 /* Present? We probably could not checksum such one. */
176 if (info->dlpi_phdr[j].p_flags & PF_W)
180 /* No longer storage space? No other object may succeed. */
181 if (checksum_open (info->dlpi_name) != 0)
185 start = (void *) (info->dlpi_addr + info->dlpi_phdr[j].p_vaddr);
186 end = start + info->dlpi_phdr[j].p_memsz;
187 /* Use maps_verify() after checksum_open() for more debugging info. */
188 if (maps_verify (start, end) != 0)
190 /* This object's checksum is invalid but other objects may be
193 checksum_cancel (start, end);
196 if ((void *) sigaction_orig_libc_cont < start
197 || (void *) ((char *) sigaction_orig_libc_cont - trampoline_size)
199 checksum_data (&obj->checksum, start, end);
202 checksum_data (&obj->checksum, start,
203 (char *) sigaction_orig_libc_cont - trampoline_size);
204 checksum_data (&obj->checksum, sigaction_trampoline,
205 (char *) sigaction_trampoline + trampoline_size);
206 checksum_data (&obj->checksum, sigaction_orig_libc_cont, end);
216 INTERNAL void core_dump (void)
218 const char *msg = "libobjid: core\n";
219 write (STDERR_FILENO, msg, strlen (msg));
224 dl_iterate_phdr (phdr_callback, NULL);