PATCH(1/2) libdl and rtems-tools. Add zlib compression for rap files

Сергей Круглов sergkruglov at bk.ru
Tue Feb 26 07:05:15 UTC 2019


cpukit/include/rtems/rtl/rtl-obj-comp.h
cpukit/libdl/rtl-obj-comp.c
cpukit/libdl/rtl-rap.c

diff -Naur cpukit/include/rtl/rtl-obj-comp.h cpukit_patched/include/rtl/rtl-obj-comp.h
--- cpukit/include/rtl/rtl-obj-comp.h    2018-10-22 15:05:16 +0400
+++ cpukit_patched/include/rtl/rtl-obj-comp.h    2019-02-15 16:46:26 +0400
@@ -39,6 +39,7 @@
  */
#define RTEMS_RTL_COMP_NONE (0)
#define RTEMS_RTL_COMP_LZ77 (1)
+#define RTEMS_RTL_COMP_ZLIB (2)

/**
  * The compressed file.

diff -Naur cpukit/libdl/rtl-obj-comp.c cpukit_patched/libdl/rtl-obj-comp.c
--- libdl/rtl-obj-comp.c    2018-10-22 15:05:18 +0400
+++ libdl_patched/rtl-obj-comp.c    2019-02-21 14:08:27 +0400
@@ -28,8 +28,19 @@

#include "fastlz.h"

+#include <zlib.h>
+
#include <stdio.h>

+static unsigned write_z;
+static unsigned have_z;
+static unsigned char *in_z;
+static unsigned char *out_z;
+static unsigned char *ptr_in;
+static unsigned char *ptr_out;
+static z_stream strm;
+static bool start;
+
bool
rtems_rtl_obj_comp_open (rtems_rtl_obj_comp* comp,
                          size_t              size)
@@ -46,7 +57,23 @@
     rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
     return false;
   }
+  in_z = rtems_rtl_alloc_new(RTEMS_RTL_ALLOC_OBJECT, size, false);
+  if (!in_z) 
+  {
+   rtems_rtl_set_error(ENOMEM, "no memory for compressor buffer");
+   rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
+   return false;
+  }
+  out_z = rtems_rtl_alloc_new(RTEMS_RTL_ALLOC_OBJECT, comp->size * 3, false);
+  if (!out_z) 
+  {
+   rtems_rtl_set_error(ENOMEM, "no memory for compressor buffer");
+   rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
+   rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, in_z);
+  return false;
+  }
   comp->read = 0;
+  start = true;
   return true;
}

@@ -54,6 +81,10 @@
rtems_rtl_obj_comp_close (rtems_rtl_obj_comp* comp)
{
   rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
+  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, out_z);
+  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, in_z);
+  if (comp->compression == RTEMS_RTL_COMP_ZLIB)
+   (void) inflateEnd(&strm);
   comp->cache = NULL;
   comp->fd = -1;
   comp->compression = RTEMS_RTL_COMP_LZ77;
@@ -61,6 +92,7 @@
   comp->size = 0;
   comp->offset = 0;
   comp->read = 0;
+  start = true;
}

void
@@ -70,6 +102,12 @@
                         int                  compression,
                         off_t                offset)
{
+  if (!start)
+  {
+   start = true;
+   if (compression == RTEMS_RTL_COMP_ZLIB)
+    (void) inflateEnd(&strm);
+   }
   comp->cache = cache;
   comp->fd = fd;
   comp->compression = compression;
@@ -77,13 +115,13 @@
   comp->level = 0;
   comp->read = 0;
}
-
bool
rtems_rtl_obj_comp_read (rtems_rtl_obj_comp* comp,
                          void*               buffer,
                          size_t              length)
{
   uint8_t* bin = buffer;
+  int ret_z;

   if (!comp->cache)
   {
@@ -126,25 +164,32 @@
       size_t   in_length = sizeof (block_size);
       int      decompressed;

-      if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
-                                     (void**) &input, &in_length))
-        return false;
-
-      block_size = (input[0] << 8) | input[1];
-
-      comp->offset += sizeof (block_size);
+      block_size = length > 2048 ? 2048 : length;
+            
+      if (comp->compression == RTEMS_RTL_COMP_LZ77)
+      {
+        if (!rtems_rtl_obj_cache_read(comp->cache, comp->fd,
+            comp->offset, (void**) &input, &in_length))
+          return false;
+        block_size = (input[0] << 8) | input[1];
+        comp->offset += sizeof(block_size);
+      }

       in_length = block_size;

-      if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
-                                     (void**) &input, &in_length))
-        return false;
-
-      if (in_length != block_size)
+      if ((comp->compression == RTEMS_RTL_COMP_NONE) || 
+          (comp->compression == RTEMS_RTL_COMP_LZ77)) 
       {
-        rtems_rtl_set_error (EIO, "compressed read failed: bs=%u in=%zu",
-                             block_size, in_length);
-        return false;
+        if (!rtems_rtl_obj_cache_read(comp->cache, comp->fd,
+            comp->offset, (void**) &input, &in_length))
+          return false;
+
+        if (in_length != block_size)
+        {
+          rtems_rtl_set_error(EIO,"compressed read failed: bs=%u in=%u", 
+                              block_size, in_length);
+          return false;
+        }
       }

       switch (comp->compression)
@@ -152,6 +197,7 @@
         case RTEMS_RTL_COMP_NONE:
           memcpy (comp->buffer, input, in_length);
           decompressed = in_length;
+          comp->offset += block_size;
           break;

         case RTEMS_RTL_COMP_LZ77:
@@ -162,15 +208,79 @@
             rtems_rtl_set_error (EBADF, "decompression failed");
             return false;
           }
+          comp->offset += block_size;
           break;
+        case RTEMS_RTL_COMP_ZLIB:
+          if (start) 
+          {
+            start = false;
+            strm.zalloc = Z_NULL;
+            strm.zfree = Z_NULL;
+            strm.opaque = Z_NULL;
+            strm.avail_in = 0;
+            strm.next_in = Z_NULL;
+            ret_z = inflateInit(&strm);
+            if (ret_z != Z_OK)
+            {
+              rtems_rtl_set_error(EBADF, "Invalid init inflate");
+              return false;
+            }
+            ptr_in = out_z;
+            have_z = 0;
+          }
+          ptr_out = comp->buffer;
+          write_z = 0;
+          while (1)
+          {
+           while (have_z > 0)
+           {
+             write_z = have_z > (block_size - (ptr_out - comp->buffer)) ?
+                       block_size - (ptr_out - comp->buffer) : have_z;
+             memcpy(ptr_out, ptr_in, write_z);
+             ptr_out += write_z;
+             ptr_in += write_z;
+             have_z -= write_z;
+             if ((ptr_out - comp->buffer) == block_size)
+               break;
+           }
+           if ((ptr_out - comp->buffer) == block_size)
+             break;
+           if (strm.avail_in == 0) 
+           {
+             strm.avail_in = comp->size;
+             if (!rtems_rtl_obj_cache_read(comp->cache, comp->fd,
+                 comp->offset, (void**) &in_z, &strm.avail_in))
+               return false;
+             comp->offset += strm.avail_in;
+             if (strm.avail_in == 0)
+               break;
+             strm.next_in = in_z;
+           }
+           strm.avail_out = comp->size * 3;
+           strm.next_out = out_z;
+           ptr_in = out_z;
+           ret_z = inflate(&strm, Z_NO_FLUSH);
+           if ((ret_z == Z_STREAM_ERROR) || (ret_z == Z_NEED_DICT) ||
+               (ret_z == Z_DATA_ERROR) || (ret_z == Z_MEM_ERROR))
+           {
+             rtems_rtl_set_error(EBADF, "Invalid inflate");
+             return false;
+           }
+           have_z = comp->size * 3 - strm.avail_out;
+          }
+           decompressed = ptr_out - comp->buffer;
+           if (decompressed == 0)
+           {
+             rtems_rtl_set_error(EBADF, "decompression failed");
+             return false;
+           }
+           break;

         default:
           rtems_rtl_set_error (EINVAL, "bad compression type");
           return false;
       }

-      comp->offset += block_size;
-
       comp->level = decompressed;
     }
   }

diff -Naur cpukit/libdl/rtl-rap.c cpukit_patched/libdl/rtl-rap.c
--- libdl/rtl-rap.c    2019-02-18 16:36:20 +0400
+++ libdl_patched/rtl-rap.c    2019-02-21 11:23:33 +0400
@@ -626,6 +626,10 @@
     if (rtems_rtl_symbol_global_find (rap->strtab + name) &&
         (ELF_ST_BIND (data & 0xffff) != STB_WEAK))
     {
+      printf("Warning:duplicate global symbol: %s, use kernel symbol\n", rap->strtab + name);
+      obj->global_syms--; // for use --gc-sections (ld) and -ffunction-sections -fdata-sections (gcc)
+      continue;
+/*
       rtems_rtl_set_error (EINVAL,
                            "duplicate global symbol: %s", rap->strtab + name);
       rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
@@ -633,6 +637,7 @@
       obj->global_syms = 0;
       obj->global_size = 0;
       return false;
+*/
     }

     symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16);
@@ -731,7 +736,15 @@
     *compression = RTEMS_RTL_COMP_LZ77;
     eptr = sptr + 4;
   }
-  else
+  else if ((sptr[0] == 'Z') &&
+           (sptr[1] == 'L') && 
+           (sptr[2] == 'I') &&
+           (sptr[3] == 'B')) 
+  {
+    *compression = RTEMS_RTL_COMP_ZLIB;
+    eptr = sptr + 4;
+  }
+  else 
     return false;

   if (*eptr != ',')

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/users/attachments/20190226/0ee3356f/attachment-0001.html>


More information about the users mailing list