libdwfl: Support LZMA kernel images.
authorRoland McGrath <roland@redhat.com>
Wed, 26 Aug 2009 10:05:50 +0000 (03:05 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 26 Aug 2009 10:05:50 +0000 (03:05 -0700)
NEWS
libdwfl/ChangeLog
libdwfl/gzip.c

diff --git a/NEWS b/NEWS
index 0f964d7..992ffd2 100644 (file)
--- 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:
 
index 46c70b3..9d2bf8c 100644 (file)
@@ -1,5 +1,10 @@
 2009-08-26  Roland McGrath  <roland@redhat.com>
 
+       * 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.
index 67f203f..daf250b 100644 (file)
 #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;