Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid SEGV in crash dump of global literals on debug target #8974

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion erts/emulator/beam/atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ atom_alloc(Atom* tmpl)
0,
tmpl->len,
tmpl->u.name);
erts_global_literal_register(&obj->u.bin, hp, heap_size);
erts_global_literal_register(&obj->u.bin);
}

obj->len = tmpl->len;
Expand Down
2 changes: 1 addition & 1 deletion erts/emulator/beam/beam_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ void beamfile_init(void) {
hp = erts_global_literal_allocate(8, &ohp);
suffix = erts_bin_bytes_to_list(NIL, hp, (byte*)".erl", 4, 0);

erts_global_literal_register(&suffix, hp, 8);
erts_global_literal_register(&suffix);
ERTS_GLOBAL_LIT_ERL_FILE_SUFFIX = suffix;
}

Expand Down
2 changes: 1 addition & 1 deletion erts/emulator/beam/dist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ void init_dist(void)
if (hpp) {
ASSERT(is_value(tuple));
ASSERT(hp == hp_start + sz);
erts_global_literal_register(&tuple, hp, sz);
erts_global_literal_register(&tuple);
ERTS_GLOBAL_LIT_DFLAGS_RECORD = tuple;
break;
}
Expand Down
4 changes: 2 additions & 2 deletions erts/emulator/beam/erl_bif_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -6273,7 +6273,7 @@ static void os_info_init(void)

hp = erts_global_literal_allocate(3, &ohp);
tuple = TUPLE2(hp, type, flav);
erts_global_literal_register(&tuple, hp, 3);
erts_global_literal_register(&tuple);
ERTS_GLOBAL_LIT_OS_TYPE = tuple;

hp = erts_global_literal_allocate(4, &ohp);
Expand All @@ -6282,7 +6282,7 @@ static void os_info_init(void)
make_small(major),
make_small(minor),
make_small(build));
erts_global_literal_register(&tuple, hp, 4);
erts_global_literal_register(&tuple);
ERTS_GLOBAL_LIT_OS_VERSION = tuple;
}

Expand Down
63 changes: 38 additions & 25 deletions erts/emulator/beam/erl_global_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ erts_mtx_t global_literal_lock;
* This is protected by the global literal lock. */
struct global_literal_chunk {
struct global_literal_chunk *next;
Eterm *hp;
Eterm *chunk_end;

ErtsLiteralArea area;
} *global_literal_chunk = NULL;

/* The size of the global literal term that is being built */
Uint global_literal_build_size;


ErtsLiteralArea *erts_global_literal_iterate_area(ErtsLiteralArea *prev)
Expand All @@ -81,7 +83,6 @@ ErtsLiteralArea *erts_global_literal_iterate_area(ErtsLiteralArea *prev)
next = global_literal_chunk;
}

next->area.end = next->hp;
return &next->area;
}

Expand All @@ -100,10 +101,14 @@ static void expand_shared_global_literal_area(Uint heap_size)
address = (UWord) erts_alloc(ERTS_ALC_T_LITERAL, size + sys_page_size * 2);
address = (address + (sys_page_size - 1)) & ~(sys_page_size - 1);
chunk = (struct global_literal_chunk *) address;

for (int i = 0; i < heap_size; i++) {
chunk->area.start[i] = ERTS_HOLE_MARKER;
}
#endif

chunk->hp = &chunk->area.start[0];
chunk->area.end = &chunk->hp[heap_size];
chunk->area.end = &(chunk->area.start[0]);
chunk->chunk_end = &(chunk->area.start[heap_size]);
chunk->area.off_heap = NULL;
chunk->next = global_literal_chunk;

Expand All @@ -112,45 +117,53 @@ static void expand_shared_global_literal_area(Uint heap_size)

Eterm *erts_global_literal_allocate(Uint heap_size, struct erl_off_heap_header ***ohp)
{
Eterm *hp;

erts_mtx_lock(&global_literal_lock);

ASSERT((global_literal_chunk->hp <= global_literal_chunk->area.end &&
global_literal_chunk->hp >= global_literal_chunk->area.start) );
if (global_literal_chunk->area.end - global_literal_chunk->hp <= heap_size) {
ASSERT(global_literal_chunk->area.end <= global_literal_chunk->chunk_end &&
global_literal_chunk->area.end >= global_literal_chunk->area.start);
if (global_literal_chunk->chunk_end - global_literal_chunk->area.end < heap_size) {
expand_shared_global_literal_area(heap_size + GLOBAL_LITERAL_EXPAND_SIZE);
}

*ohp = &global_literal_chunk->area.off_heap;

#ifdef DEBUG
{
struct global_literal_chunk *chunk = global_literal_chunk;
erts_mem_guard(chunk,
(chunk->area.end - (Eterm*)chunk) * sizeof(Eterm),
(byte*)(chunk->area.end + heap_size) - (byte*)chunk,
1,
1);
}
#endif

global_literal_build_size = heap_size;

*ohp = &global_literal_chunk->area.off_heap;
hp = global_literal_chunk->hp;
global_literal_chunk->hp += heap_size;

return hp;
return global_literal_chunk->area.end;
}

void erts_global_literal_register(Eterm *variable, Eterm *hp, Uint heap_size) {
erts_set_literal_tag(variable, hp, heap_size);
void erts_global_literal_register(Eterm *variable) {
struct global_literal_chunk *chunk = global_literal_chunk;

ASSERT(ptr_val(*variable) >= chunk->area.end &&
ptr_val(*variable) < (chunk->area.end + global_literal_build_size));

erts_set_literal_tag(variable,
chunk->area.end,
global_literal_build_size);

chunk->area.end += global_literal_build_size;

ASSERT(chunk->area.end <= chunk->chunk_end &&
chunk->area.end >= chunk->area.start);
ASSERT(chunk->area.end == chunk->chunk_end ||
chunk->area.end[0] == ERTS_HOLE_MARKER);

#ifdef DEBUG
{
struct global_literal_chunk *chunk = global_literal_chunk;
erts_mem_guard(chunk,
(chunk->area.end - (Eterm*)chunk) * sizeof(Eterm),
1,
0);
}
erts_mem_guard(chunk,
(byte*)chunk->chunk_end - (byte*)chunk,
1,
0);
#endif

erts_mtx_unlock(&global_literal_lock);
Expand All @@ -163,7 +176,7 @@ static void init_empty_tuple(void) {
hp[0] = make_arityval_zero();
hp[1] = make_arityval_zero();
tuple = make_tuple(hp);
erts_global_literal_register(&tuple, hp, 2);
erts_global_literal_register(&tuple);
ERTS_GLOBAL_LIT_EMPTY_TUPLE = tuple;
}

Expand Down
2 changes: 1 addition & 1 deletion erts/emulator/beam/erl_global_literals.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Eterm *erts_global_literal_allocate(Uint sz, struct erl_off_heap_header ***ohp);

/* Registers the pointed-to term as a global literal. Must be called for terms
* allocated using erts_global_literal_allocate.*/
void erts_global_literal_register(Eterm *variable, Eterm *hp, Uint heap_size);
void erts_global_literal_register(Eterm *variable);

/* Iterates between global literal areas. Can only be used when crash dumping.
* Iteration is started by passing NULL, then successively calling this function
Expand Down
2 changes: 1 addition & 1 deletion erts/emulator/beam/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static void create_shared_lambda(Export *export)

export->lambda = make_fun(lambda);

erts_global_literal_register(&export->lambda, (Eterm*)lambda, ERL_FUN_SIZE);
erts_global_literal_register(&export->lambda);
}

static HashValue export_hash(const Export *export)
Expand Down
Loading