diff options
author | Eugene Tarassov | 2018-09-29 17:09:02 +0000 |
---|---|---|
committer | Eugene Tarassov | 2018-09-29 22:45:37 +0000 |
commit | 75efc857b76bc382b44fc3c17cf9bbf078d5e64a (patch) | |
tree | 99ced14bf62c53b56193793d3bddcd69896912ca | |
parent | 3a619d62c9e78bb032963c0ee687c7c5c5318d21 (diff) | |
download | org.eclipse.tcf.agent-1.6.tar.gz org.eclipse.tcf.agent-1.6.tar.xz org.eclipse.tcf.agent-1.6.zip |
TCF Agent: fixed handling of overlapping memory map regions on Linux1.6
-rw-r--r-- | agent/system/GNU/Linux/tcf/context-linux.c | 69 | ||||
-rw-r--r-- | agent/tcf/services/tcf_elf.c | 25 |
2 files changed, 72 insertions, 22 deletions
diff --git a/agent/system/GNU/Linux/tcf/context-linux.c b/agent/system/GNU/Linux/tcf/context-linux.c index d4eb5e6b..31a79d56 100644 --- a/agent/system/GNU/Linux/tcf/context-linux.c +++ b/agent/system/GNU/Linux/tcf/context-linux.c @@ -1065,7 +1065,7 @@ int context_get_memory_map(Context * ctx, MemoryMap * map) { &addr0, &addr1, permissions, &offset, &dev_ma, &dev_mi, &inode); if (cnt == 0 || cnt == EOF) break; - for (;;) { + for (i = 0;;) { int ch = fgetc(file); if (ch == '\n' || ch == EOF) break; if (i < FILE_PATH_SIZE - 1 && (ch != ' ' || i > 0)) { @@ -1091,27 +1091,52 @@ int context_get_memory_map(Context * ctx, MemoryMap * map) { if (map->region_cnt > 0) prev = map->regions + (map->region_cnt - 1); if (inode != 0 && file_name[0] && file_name[0] != '[') { - MemoryRegion * r = map->regions + map->region_cnt++; - memset(r, 0, sizeof(MemoryRegion)); - r->addr = addr0; - r->size = addr1 - addr0; - r->flags = flags; - r->file_offs = offset; - r->dev = MKDEV(dev_ma, dev_mi); - r->ino = (ino_t)inode; - r->file_name = loc_strdup(file_name); - } - else if (file_name[0] == 0 && prev != NULL && prev->addr + prev->size == addr0) { - MemoryRegion * r = map->regions + map->region_cnt++; - memset(r, 0, sizeof(MemoryRegion)); - r->bss = 1; - r->addr = addr0; - r->size = addr1 - addr0; - r->flags = flags; - r->file_offs = prev->file_offs + prev->size; - r->dev = prev->dev; - r->ino = prev->ino; - r->file_name = loc_strdup(prev->file_name); + if (prev != NULL && (prev->flags & MM_FLAG_X) == 0 && + prev->file_size == prev->size && prev->dev == MKDEV(dev_ma, dev_mi) && prev->ino == (ino_t)inode && + prev->file_offs + prev->file_size == offset && prev->addr + prev->size == addr0) { + prev->file_size += addr1 - addr0; + prev->size += addr1 - addr0; + prev->flags |= flags; + } + else { + MemoryRegion * r = map->regions + map->region_cnt++; + memset(r, 0, sizeof(MemoryRegion)); + r->addr = addr0; + r->valid |= MM_VALID_ADDR; + r->size = addr1 - addr0; + r->valid |= MM_VALID_SIZE; + r->flags = flags; + r->file_offs = offset; + r->valid |= MM_VALID_FILE_OFFS; + r->file_size = addr1 - addr0; + r->valid |= MM_VALID_FILE_SIZE; + r->dev = MKDEV(dev_ma, dev_mi); + r->ino = (ino_t)inode; + r->file_name = loc_strdup(file_name); + } + } + else if ((file_name[0] == 0 || strcmp(file_name, "[heap]") == 0) && + prev != NULL && prev->addr + prev->size == addr0) { + if ((prev->flags & MM_FLAG_X) == 0) { + prev->size += addr1 - addr0; + prev->flags |= flags; + } + else { + MemoryRegion * r = map->regions + map->region_cnt++; + memset(r, 0, sizeof(MemoryRegion)); + r->bss = 1; + r->addr = addr0; + r->valid |= MM_VALID_ADDR; + r->size = addr1 - addr0; + r->valid |= MM_VALID_SIZE; + r->flags = flags; + r->file_offs = prev->file_offs + prev->size; + r->valid |= MM_VALID_FILE_OFFS; + r->valid |= MM_VALID_FILE_SIZE; + r->dev = prev->dev; + r->ino = prev->ino; + r->file_name = loc_strdup(prev->file_name); + } } } fclose(file); diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c index cd82bcbd..6cf929a4 100644 --- a/agent/tcf/services/tcf_elf.c +++ b/agent/tcf/services/tcf_elf.c @@ -1387,6 +1387,7 @@ static void search_regions(MemoryMap * map, ContextAddress addr0, ContextAddress } int elf_get_map(Context * ctx, ContextAddress addr0, ContextAddress addr1, MemoryMap * map) { + unsigned i; map->region_cnt = 0; ctx = context_get_group(ctx, CONTEXT_GROUP_PROCESS); #if ENABLE_MemoryMap @@ -1412,6 +1413,30 @@ int elf_get_map(Context * ctx, ContextAddress addr0, ContextAddress addr1, Memor } } #endif + for (i = 0; i + 1 < map->region_cnt; i++) { + MemoryRegion * m = map->regions + i; + MemoryRegion * r = m + 1; + if (m->file_size == m->size && m->file_offs < r->file_offs && m->file_offs + m->file_size > r->file_offs && + m->file_name != NULL && r->file_name != NULL && strcmp(m->file_name, r->file_name) == 0) { + /* Ambiguity: overlapping regions */ + ELF_File * elf = elf_open(r->file_name); + for (i = 0; i < elf->pheader_cnt; i++) { + ELF_PHeader * p = elf->pheaders + i; + if (p->type == PT_LOAD && p->offset == m->file_offs && p->mem_size < m->size) { + m->file_size = p->mem_size; + m->size = p->mem_size; + if (m->file_offs + m->size > r->file_offs && p->mem_size == p->file_size) { + uint64_t diff = m->file_offs + m->file_size - r->file_offs; + r->file_offs += diff; + r->file_size -= diff; + r->addr += diff; + r->size -= diff; + } + break; + } + } + } + } return 0; } |