summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--libdwfl/ChangeLog5
-rw-r--r--libdwfl/gzip.c30
3 files changed, 36 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 0f964d76..992ffd28 100644
--- a/NEWS
+++ b/NEWS
@@ -3,8 +3,8 @@ Version 0.143:
libdw: Various convenience functions for individual attributes now use
dwarf_attr_integrate to look up indirect inherited attributes.
-libdwfl: Support Linux bzip2 kernel images for automatic decompression.
- Support automatic decompression of files in XZ format.
+libdwfl: Support automatic decompression of files in XZ format,
+ and of Linux kernel images made with bzip2 or LZMA (as well as gzip).
Version 0.142:
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 46c70b30..9d2bf8c7 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,10 @@
2009-08-26 Roland McGrath <[email protected]>
+ * gzip.c (find_zImage_payload): New function, broken out of ...
+ (mapped_zImage): ... here. Call it.
+ (find_zImage_payload) [LZMA]: Match LZMA-compressed kernels with
+ stupid method of just trying the decoder.
+
* open.c [USE_LZMA]: Try __libdw_unlzma.
* libdwflP.h: Declare it.
(DWFL_ERRORS): Add DWFL_E_LZMA.
diff --git a/libdwfl/gzip.c b/libdwfl/gzip.c
index 67f203f8..daf250bb 100644
--- a/libdwfl/gzip.c
+++ b/libdwfl/gzip.c
@@ -93,6 +93,34 @@
#define LINUX_MAGIC "HdrS"
#define LINUX_MAX_SCAN 32768
+static void *
+find_zImage_payload (void *buffer, size_t size)
+{
+ void *p = memmem (buffer, size, MAGIC, sizeof MAGIC - 1);
+#ifdef LZMA
+ /* The raw LZMA format doesn't have any helpful header magic bytes to
+ match. So instead we just consider any byte that could possibly be
+ the start of an LZMA header, and try feeding the input to the decoder
+ to see if it likes the data. */
+ if (p == NULL)
+ for (; size > 0; ++buffer, --size)
+ if (*(uint8_t *) buffer < (9 * 5 * 5))
+ {
+ uint8_t dummy[512];
+ lzma_stream z = { .next_in = buffer, .avail_in = size,
+ .next_out = dummy, .avail_out = sizeof dummy };
+ int result = lzma_alone_decoder (&z, 1 << 30);
+ if (result != LZMA_OK)
+ break;
+ result = lzma_code (&z, LZMA_RUN);
+ lzma_end (&z);
+ if (result == LZMA_OK)
+ return buffer;
+ }
+#endif
+ return p;
+}
+
static bool
mapped_zImage (off64_t *start_offset, void **mapped, size_t *mapped_size)
{
@@ -104,7 +132,7 @@ mapped_zImage (off64_t *start_offset, void **mapped, size_t *mapped_size)
size_t scan = *mapped_size - pos;
if (scan > LINUX_MAX_SCAN)
scan = LINUX_MAX_SCAN;
- void *p = memmem (*mapped + pos, scan, MAGIC, sizeof MAGIC - 1);
+ void *p = find_zImage_payload (*mapped + pos, scan);
if (p != NULL)
{
*start_offset += p - *mapped;