From: Michael Tremer Date: Fri, 3 Jan 2025 06:04:06 +0000 (+0000) Subject: ELF: Move any source file handling X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7fd7da716b5fc0b7879371ecb77e92b564997177;p=people%2Fric9%2Fpakfire.git ELF: Move any source file handling Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/elf.c b/src/libpakfire/elf.c index f3bff5bf5..148cf254f 100644 --- a/src/libpakfire/elf.c +++ b/src/libpakfire/elf.c @@ -26,6 +26,7 @@ #include #include #include +#include #include // libelf @@ -854,3 +855,104 @@ int pakfire_elf_is_stripped(struct pakfire_elf* self) { // Otherwise we assume the binary being stripped return 1; } + +/* + libdw does not seem to export the error codes in their header files, + although there is a function to retrieve them... +*/ +#ifndef DWARF_E_NO_DWARF +#define DWARF_E_NO_DWARF 6 +#endif + +int pakfire_elf_foreach_source_file(struct pakfire_elf* self, + pakfire_elf_foreach_source_file_callback callback, void* data) { + const char* filename = NULL; + char basename[PATH_MAX]; + char path[PATH_MAX]; + Dwarf* dwarf = NULL; + Dwarf_Files* files = NULL; + Dwarf_Die* die = NULL; + Dwarf_Off offset = 0; + Dwarf_Off next_offset; + size_t cu_header_length; + Dwarf_Die die_mem; + size_t count; + int r; + + // Read DWARF information + dwarf = dwarf_begin(self->fd, DWARF_C_READ); + if (!dwarf) { + switch (dwarf_errno()) { + // If we don't have any DWARF information there is nothing to do + case DWARF_E_NO_DWARF: + r = 0; + goto ERROR; + + default: + ERROR(self->ctx, "Could not initialize DWARF context: %s\n", dwarf_errmsg(-1)); + r = -errno; + goto ERROR; + } + } + + for (;;) { + // Fetch the next compilation unit + r = dwarf_nextcu(dwarf, offset, &next_offset, &cu_header_length, NULL, NULL, NULL); + if (r < 0) + goto ERROR; + + // Fetch the Debug Information Entry + die = dwarf_offdie(dwarf, offset + cu_header_length, &die_mem); + if (!die) + break; + + // Fetch the source files + r = dwarf_getsrcfiles(die, &files, &count); + if (r < 0) { + ERROR(self->ctx, "Could not fetch the source files: %s\n", dwarf_errmsg(-1)); + r = -errno; + goto ERROR; + } + + // Iterate over all files... + for (unsigned int i = 0; i < count; i++) { + // Fetch the filename + filename = dwarf_filesrc(files, i, NULL, NULL); + + // Copy to the stack + r = pakfire_string_set(path, filename); + if (r < 0) + goto ERROR; + + // Normalize the path + r = pakfire_path_normalize(path); + if (r < 0) + goto ERROR; + + // Determine the basename + r = pakfire_path_basename(basename, filename); + if (r < 0) + goto ERROR; + + // Ignore things like or + if (pakfire_string_startswith(basename, "<") + && pakfire_string_endswith(basename, ">")) + continue; + + DEBUG(self->ctx, "Found source file: %s\n", path); + + // Call the callback + r = callback(self->ctx, self, path, data); + if (r) + goto ERROR; + } + + offset = next_offset; + } + +ERROR: + if (dwarf) + dwarf_end(dwarf); + + return r; +} diff --git a/src/libpakfire/include/pakfire/elf.h b/src/libpakfire/include/pakfire/elf.h index 02de846d1..f723d5224 100644 --- a/src/libpakfire/include/pakfire/elf.h +++ b/src/libpakfire/include/pakfire/elf.h @@ -61,6 +61,13 @@ enum { PAKFIRE_ELF_MISSING_SHSTK = (1 << 3), }; +// Source Files +typedef int (*pakfire_elf_foreach_source_file_callback) + (struct pakfire_ctx* ctx, struct pakfire_elf* elf, const char* filename, void* data); + +int pakfire_elf_foreach_source_file(struct pakfire_elf* self, + pakfire_elf_foreach_source_file_callback callback, void* data); + #endif /* PAKFIRE_PRIVATE */ #endif /* PAKFIRE_ELF_H */ diff --git a/src/libpakfire/stripper.c b/src/libpakfire/stripper.c index eaa9c3b0f..90546f6a6 100644 --- a/src/libpakfire/stripper.c +++ b/src/libpakfire/stripper.c @@ -19,14 +19,11 @@ #############################################################################*/ #include +#include #include #include #include -// libdw -#include -#include - #include #include #include @@ -52,8 +49,28 @@ struct pakfire_stripper { // Filelist struct pakfire_filelist* filelist; + + // Source Directory + int sourcesfd; }; +static int pakfire_stripper_open_sources(struct pakfire_stripper* stripper) { + // Open the source directory + stripper->sourcesfd = pakfire_openat(stripper->pakfire, BUILD_SRC_DIR, O_DIRECTORY|O_PATH); + if (stripper->sourcesfd < 0) { + switch (errno) { + case ENOENT: + break; + + default: + ERROR(stripper->ctx, "Could not open %s: %m\n", BUILD_SRC_DIR); + return -errno; + } + } + + return 0; +} + int pakfire_stripper_create(struct pakfire_stripper** stripper, struct pakfire* pakfire, struct pakfire_jail* jail, const char* path) { struct pakfire_stripper* s = NULL; @@ -76,6 +93,9 @@ int pakfire_stripper_create(struct pakfire_stripper** stripper, // Initialize the reference counter s->nrefs = 1; + // Initialize file descriptors + s->sourcesfd = -EBADF; + // Store the path r = pakfire_string_set(s->path, path); if (r < 0) @@ -86,6 +106,11 @@ int pakfire_stripper_create(struct pakfire_stripper** stripper, if (r < 0) goto ERROR; + // Open the source directory + r = pakfire_stripper_open_sources(s); + if (r < 0) + goto ERROR; + // Return the pointer *stripper = pakfire_stripper_ref(s); @@ -97,6 +122,8 @@ ERROR: } static void pakfire_stripper_free(struct pakfire_stripper* stripper) { + if (stripper->sourcesfd) + close(stripper->sourcesfd); if (stripper->filelist) pakfire_filelist_unref(stripper->filelist); if (stripper->pakfire) @@ -167,65 +194,58 @@ ERROR: } static int pakfire_stripper_copy_source_file( - struct pakfire_stripper* stripper, const char* filename) { - char srcpath[PATH_MAX]; - char dstpath[PATH_MAX]; + struct pakfire_ctx* ctx, struct pakfire_elf* elf, const char* filename, void* data) { + struct pakfire_stripper* stripper = data; + char path[PATH_MAX]; struct stat st = {}; - int r; - - FILE* src = NULL; FILE* dst = NULL; + int fd = -EBADF; + int r; - // Make the source path absolute - r = pakfire_path(stripper->pakfire, srcpath, "%s", filename); - if (r < 0) - goto ERROR; + // If the source file is not in the right path, we ignore it + if (!pakfire_string_startswith(filename, DEBUG_SRC_DIR)) + return 0; // Remove the original source path - r = pakfire_path_relative(dstpath, BUILD_SRC_DIR, filename); - if (r < 0) - goto ERROR; - - // Add the debug directory source path - r = pakfire_path_append(dstpath, DEBUG_SRC_DIR, dstpath); - if (r < 0) - goto ERROR; - - // Add the buildroot - r = pakfire_path_append(dstpath, stripper->path, dstpath); + r = pakfire_path_relative(path, DEBUG_SRC_DIR, filename); if (r < 0) goto ERROR; // Open the source file - src = fopen(srcpath, "r"); - if (!src) { + fd = openat(stripper->sourcesfd, path, O_RDONLY); + if (fd < 0) { switch (errno) { // If the source file does not exist, we cannot copy anything - case ENOENT: - goto ERROR; + //case ENOENT: + // goto ERROR; default: - ERROR(stripper->ctx, "Could not open %s: %m\n", filename); + ERROR(stripper->ctx, "Could not open %s: %m\n", path); r = -errno; goto ERROR; } } // Stat the source file - r = fstat(fileno(src), &st); + r = fstat(fd, &st); if (r < 0) { - ERROR(stripper->ctx, "Could not stat %s: %m\n", filename); + ERROR(stripper->ctx, "Could not stat %s: %m\n", path); r = -errno; goto ERROR; } + // Add the buildroot + r = pakfire_path_append(path, stripper->path, filename); + if (r < 0) + goto ERROR; + // Create all directories - r = pakfire_mkparentdir(dstpath, 0755); + r = pakfire_mkparentdir(path, 0755); if (r < 0) goto ERROR; // Open the destination file - dst = fopen(dstpath, "wx"); + dst = fopen(path, "wx"); if (!dst) { switch (errno) { // If the file exist already, we are done @@ -233,14 +253,14 @@ static int pakfire_stripper_copy_source_file( goto ERROR; default: - ERROR(stripper->ctx, "Could not open %s: %m\n", dstpath); + ERROR(stripper->ctx, "Could not open %s: %m\n", path); r = -errno; goto ERROR; } } // Copy all content - ssize_t bytes_written = sendfile(fileno(dst), fileno(src), 0, st.st_size); + ssize_t bytes_written = sendfile(fileno(dst), fd, 0, st.st_size); if (bytes_written < st.st_size) { ERROR(stripper->ctx, "Failed to copy source file %s: %m\n", filename); r = -errno; @@ -250,7 +270,7 @@ static int pakfire_stripper_copy_source_file( // Change permissions r = fchmod(fileno(dst), 0444); if (r < 0) { - ERROR(stripper->ctx, "Could not change permissions of %s: %m\n", dstpath); + ERROR(stripper->ctx, "Could not change permissions of %s: %m\n", path); r = -errno; goto ERROR; } @@ -258,103 +278,8 @@ static int pakfire_stripper_copy_source_file( ERROR: if (dst) fclose(dst); - if (src) - fclose(src); - - return r; -} - -/* - libdw does not seem to export the error codes in their header files, - although there is a function to retrieve them... -*/ -#ifndef DWARF_E_NO_DWARF -#define DWARF_E_NO_DWARF 6 -#endif - -static int pakfire_stripper_copy_sources( - struct pakfire_stripper* stripper, struct pakfire_file* file, int fd) { - const char* filename = NULL; - char basename[PATH_MAX]; - Dwarf* dwarf = NULL; - Dwarf_Files* files = NULL; - Dwarf_Die* die = NULL; - Dwarf_Off offset = 0; - Dwarf_Off next_offset; - size_t cu_header_length; - Dwarf_Die die_mem; - size_t count; - int r; - - // Read DWARF information - dwarf = dwarf_begin(fd, DWARF_C_READ); - if (!dwarf) { - switch (dwarf_errno()) { - // If we don't have any DWARF information there is nothing to do - case DWARF_E_NO_DWARF: - r = 0; - goto ERROR; - - default: - ERROR(stripper->ctx, "Could not initialize DWARF context: %s\n", dwarf_errmsg(-1)); - r = -errno; - goto ERROR; - } - } - - for (;;) { - // Fetch the next compilation unit - r = dwarf_nextcu(dwarf, offset, &next_offset, &cu_header_length, NULL, NULL, NULL); - if (r < 0) - goto ERROR; - - // Fetch the Debug Information Entry - die = dwarf_offdie(dwarf, offset + cu_header_length, &die_mem); - if (!die) - break; - - // Fetch the source files - r = dwarf_getsrcfiles(die, &files, &count); - if (r < 0) { - ERROR(stripper->ctx, "Could not fetch the source files: %s\n", dwarf_errmsg(-1)); - r = -errno; - goto ERROR; - } - - // Iterate over all files... - for (unsigned int i = 0; i < count; i++) { - // Fetch the filename - filename = dwarf_filesrc(files, i, NULL, NULL); - - // If the source file is not in the right path, we ignore it - if (!pakfire_string_startswith(filename, BUILD_SRC_DIR)) - continue; - - // Determine the basename - r = pakfire_path_basename(basename, filename); - if (r < 0) - goto ERROR; - - // Ignore things like or - if (pakfire_string_startswith(basename, "<") && pakfire_string_endswith(basename, ">")) - continue; - - DEBUG(stripper->ctx, "Found source file: %s\n", filename); - - // Copy the file - r = pakfire_stripper_copy_source_file(stripper, filename); - if (r < 0) { - ERROR(stripper->ctx, "Could not copy source file %s: %s\n", filename, strerror(-r)); - goto ERROR; - } - } - - offset = next_offset; - } - -ERROR: - if (dwarf) - dwarf_end(dwarf); + if (fd >= 0) + close(fd); return r; } @@ -434,8 +359,8 @@ static int pakfire_stripper_strip_debug_sections(struct pakfire_stripper* stripp // The command returned an error } else if (r > 0) { - ERROR(stripper->ctx, "Could not extract debug sections from %s\n", - pakfire_file_get_path(file)); + ERROR(stripper->ctx, "Could not extract debug sections from %s: %d\n", + pakfire_file_get_path(file), r); return -ENOTSUP; } @@ -490,16 +415,8 @@ static int pakfire_stripper_strip( struct pakfire_ctx* ctx, struct pakfire_file* file, void* data) { struct pakfire_stripper* stripper = data; struct pakfire_elf* elf = NULL; - int fd = -EBADF; int r; - // Open the file - fd = pakfire_file_open(file, 0); - if (fd < 0) { - r = -errno; - goto ERROR; - } - // Open the ELF file r = pakfire_elf_open_file(&elf, stripper->ctx, file); if (r < 0) @@ -508,7 +425,8 @@ static int pakfire_stripper_strip( // Only strip if there is actually some debug information if (!pakfire_elf_is_stripped(elf)) { // Copy sources - r = pakfire_stripper_copy_sources(stripper, file, fd); + r = pakfire_elf_foreach_source_file(elf, + pakfire_stripper_copy_source_file, stripper); if (r < 0) goto ERROR; @@ -521,8 +439,6 @@ static int pakfire_stripper_strip( ERROR: if (elf) pakfire_elf_unref(elf); - if (fd >= 0) - close(fd); return r; }