Skip to content

Commit 73ec5a0

Browse files
committed
Add support to uncompressed literal section
Starting from OTP-28 literals are not compressed anymore, so `LITT` will contain uncompressed data. OTP PR and issues contain further information about how to distinguish between compressed and uncompressed sections. See also: - erlang/otp#8940 - erlang/otp#8967 - erlang/otp#8988 Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent 30d9077 commit 73ec5a0

File tree

2 files changed

+44
-18
lines changed

2 files changed

+44
-18
lines changed

src/libAtomVM/module.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
return; \
5757
}
5858

59+
static bool module_are_literals_compressed(const uint8_t *litT);
5960
#ifdef WITH_ZLIB
6061
static void *module_uncompress_literals(const uint8_t *litT, int size);
6162
#endif
@@ -294,20 +295,26 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
294295
list_init(&mod->line_ref_offsets);
295296

296297
if (offsets[LITT]) {
297-
#ifdef WITH_ZLIB
298-
mod->literals_data = module_uncompress_literals(beam_file + offsets[LITT], sizes[LITT]);
299-
if (IS_NULL_PTR(mod->literals_data)) {
298+
if (!module_are_literals_compressed(beam_file + offsets[LITT])) {
299+
mod->literals_data = beam_file + offsets[LITT] + LITT_HEADER_SIZE;
300+
mod->free_literals_data = 0;
301+
302+
} else {
303+
#ifdef WITH_ZLIB
304+
mod->literals_data = module_uncompress_literals(beam_file + offsets[LITT], sizes[LITT]);
305+
if (IS_NULL_PTR(mod->literals_data)) {
306+
module_destroy(mod);
307+
return NULL;
308+
}
309+
mod->free_literals_data = 1;
310+
#else
311+
fprintf(stderr, "Error: zlib required to uncompress literals.\n");
300312
module_destroy(mod);
301313
return NULL;
302-
}
303-
#else
304-
fprintf(stderr, "Error: zlib required to uncompress literals.\n");
305-
module_destroy(mod);
306-
return NULL;
307-
#endif
314+
#endif
315+
}
308316

309317
mod->literals_table = module_build_literals_table(mod->literals_data);
310-
mod->free_literals_data = 1;
311318

312319
} else if (offsets[LITU]) {
313320
mod->literals_data = beam_file + offsets[LITU] + IFF_SECTION_HEADER_SIZE;
@@ -340,6 +347,12 @@ COLD_FUNC void module_destroy(Module *module)
340347
free(module);
341348
}
342349

350+
static bool module_are_literals_compressed(const uint8_t *litT)
351+
{
352+
uint32_t required_buf_size = READ_32_ALIGNED(litT + LITT_UNCOMPRESSED_SIZE_OFFSET);
353+
return (required_buf_size != 0);
354+
}
355+
343356
#ifdef WITH_ZLIB
344357
static void *module_uncompress_literals(const uint8_t *litT, int size)
345358
{

tools/packbeam/packbeam.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ typedef struct FileData {
4747
} FileData;
4848

4949
static void pad_and_align(FILE *f);
50+
bool are_literals_compressed(const uint8_t *litT);
5051
static void *uncompress_literals(const uint8_t *litT, int size, size_t *uncompressedSize);
5152
static void add_module_header(FILE *f, const char *module_name, uint32_t flags);
5253
static void pack_beam_file(FILE *pack, const uint8_t *data, size_t size, const char *filename, int is_entrypoint, bool include_lines);
@@ -338,15 +339,21 @@ static void pack_beam_file(FILE *pack, const uint8_t *data, size_t size, const c
338339
assert_fwrite(data + offsets[LINT], sizes[LINT] + IFF_SECTION_HEADER_SIZE, pack);
339340
pad_and_align(pack);
340341
}
341-
342342
if (offsets[LITT]) {
343-
size_t u_size;
344-
void *deflated = uncompress_literals(data + offsets[LITT], sizes[LITT], &u_size);
345-
assert_fwrite("LitU", 4, pack);
346-
uint32_t size_field = ENDIAN_SWAP_32(u_size);
347-
assert_fwrite(&size_field, sizeof(size_field), pack);
348-
assert_fwrite(deflated, u_size, pack);
349-
free(deflated);
343+
const uint8_t *litt = data + offsets[LITT];
344+
size_t litt_size = sizes[LITT];
345+
if (are_literals_compressed(litt)) {
346+
size_t u_size;
347+
void *deflated = uncompress_literals(data + offsets[LITT], litt_size, &u_size);
348+
assert_fwrite("LitU", 4, pack);
349+
uint32_t size_field = ENDIAN_SWAP_32(u_size);
350+
assert_fwrite(&size_field, sizeof(size_field), pack);
351+
assert_fwrite(deflated, u_size, pack);
352+
free(deflated);
353+
} else {
354+
assert_fwrite(data + offsets[LITT], sizes[LITT] + IFF_SECTION_HEADER_SIZE, pack);
355+
pad_and_align(pack);
356+
}
350357
}
351358

352359
pad_and_align(pack);
@@ -419,6 +426,12 @@ static int do_list(int argc, char **argv)
419426
return ret;
420427
}
421428

429+
bool are_literals_compressed(const uint8_t *litT)
430+
{
431+
unsigned int required_buf_size = READ_32_ALIGNED(litT + LITT_UNCOMPRESSED_SIZE_OFFSET);
432+
return (required_buf_size != 0);
433+
}
434+
422435
static void *uncompress_literals(const uint8_t *litT, int size, size_t *uncompressedSize)
423436
{
424437
unsigned int required_buf_size = READ_32_ALIGNED(litT + LITT_UNCOMPRESSED_SIZE_OFFSET);

0 commit comments

Comments
 (0)