Bug 568451 - BaseAddress for the MemoryMap
diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c
index 30918c3..ce73c47 100644
--- a/agent/tcf/services/tcf_elf.c
+++ b/agent/tcf/services/tcf_elf.c
@@ -1276,26 +1276,28 @@
     return r;
 }
 
-static void program_headers_ranges(ELF_File * file, ContextAddress addr0, ContextAddress addr1, MemoryMap * res) {
+static void program_headers_ranges(ELF_File * file, ContextAddress addr0, ContextAddress addr1, MemoryMap * res, ContextAddress base_addr) {
     unsigned j;
     for (j = 0; j < file->pheader_cnt; j++) {
         ELF_PHeader * p = file->pheaders + j;
-        if (p->mem_size == 0) continue;
-        if (p->type != PT_LOAD) continue;
-        if (p->address <= addr1 && p->address + p->mem_size - 1 >= addr0) {
-            MemoryRegion * x = add_region(res);
-            x->addr = (ContextAddress)p->address;
-            x->size = (ContextAddress)p->mem_size;
-            x->dev = file->dev;
-            x->ino = file->ino;
-            x->file_name = file->name;
-            x->file_offs = p->offset;
-            x->file_size = p->file_size;
-            x->bss = p->file_size == 0 && p->mem_size != 0;
-            if (p->flags & PF_R) x->flags |= MM_FLAG_R;
-            if (p->flags & PF_W) x->flags |= MM_FLAG_W;
-            if (p->flags & PF_X) x->flags |= MM_FLAG_X;
-            x->valid = MM_VALID_ADDR | MM_VALID_SIZE | MM_VALID_FILE_OFFS | MM_VALID_FILE_SIZE;
+        if (p->type == PT_LOAD && p->mem_size > 0) {
+            ContextAddress p_addr0 = (ContextAddress)p->address + base_addr;
+            ContextAddress p_addr1 = (ContextAddress)(p->address + p->mem_size - 1) + base_addr;
+            if (p_addr0 <= addr1 && p_addr1 >= addr0) {
+                MemoryRegion * x = add_region(res);
+                x->addr = p_addr0;
+                x->size = (ContextAddress)p->mem_size;
+                x->dev = file->dev;
+                x->ino = file->ino;
+                x->file_name = file->name;
+                x->file_offs = p->offset;
+                x->file_size = p->file_size;
+                x->bss = p->file_size == 0 && p->mem_size != 0;
+                if (p->flags & PF_R) x->flags |= MM_FLAG_R;
+                if (p->flags & PF_W) x->flags |= MM_FLAG_W;
+                if (p->flags & PF_X) x->flags |= MM_FLAG_X;
+                x->valid = MM_VALID_ADDR | MM_VALID_SIZE | MM_VALID_FILE_OFFS | MM_VALID_FILE_SIZE;
+            }
         }
     }
 }
@@ -1419,26 +1421,29 @@
         if (no_addr && no_size && no_file_offs && no_file_size && r->sect_name == NULL) {
             ELF_File * file = elf_open_memory_region_file(r, NULL);
             if (file != NULL) {
+                ContextAddress base_addr = 0;
                 KernelModuleAddress * module = NULL;
-                if (r->attrs != NULL) {
-                    MemoryRegionAttribute * a = r->attrs;
-                    while (a != NULL) {
-                        if (strcmp(a->name, "KernelModule") == 0) {
-                            ByteArrayInputStream buf;
-                            InputStream * inp = create_byte_array_input_stream(&buf, a->value, strlen(a->value));
-                            module = (KernelModuleAddress *)tmp_alloc_zero(sizeof(KernelModuleAddress));
-                            json_read_struct(inp, read_module_struct, module);
-                            json_test_char(inp, MARKER_EOS);
-                            break;
-                        }
-                        a = a->next;
+                MemoryRegionAttribute * a = r->attrs;
+                while (a != NULL) {
+                    ByteArrayInputStream buf;
+                    if (strcmp(a->name, "KernelModule") == 0) {
+                        InputStream * inp = create_byte_array_input_stream(&buf, a->value, strlen(a->value));
+                        module = (KernelModuleAddress *)tmp_alloc_zero(sizeof(KernelModuleAddress));
+                        json_read_struct(inp, read_module_struct, module);
+                        json_test_char(inp, MARKER_EOS);
                     }
+                    else if (strcmp(a->name, "BaseAddress") == 0) {
+                        InputStream * inp = create_byte_array_input_stream(&buf, a->value, strlen(a->value));
+                        base_addr = (ContextAddress)json_read_uint64(inp);
+                        json_test_char(inp, MARKER_EOS);
+                    }
+                    a = a->next;
                 }
                 if (module != NULL) {
                     linux_kernel_module_ranges(file, module, addr0, addr1, res);
                 }
                 else {
-                    program_headers_ranges(file, addr0, addr1, res);
+                    program_headers_ranges(file, addr0, addr1, res, base_addr);
                 }
             }
         }
@@ -1460,25 +1465,7 @@
                             if (p->offset == 0) break;
                         }
                     }
-                    for (j = 0; j < file->pheader_cnt; j++) {
-                        ELF_PHeader * p = file->pheaders + j;
-                        if (p->type == PT_LOAD && p->mem_size > 0) {
-                            ContextAddress p_addr0 = (ContextAddress)p->address + base_addr;
-                            ContextAddress p_addr1 = (ContextAddress)(p->address + p->mem_size - 1) + base_addr;
-                            if (p_addr0 <= addr1 && p_addr1 >= addr0) {
-                                MemoryRegion * x = add_region(res);
-                                x->addr = p_addr0;
-                                x->size = (ContextAddress)p->mem_size;
-                                x->dev = file->dev;
-                                x->ino = file->ino;
-                                x->file_name = file->name;
-                                x->file_offs = p->offset;
-                                x->file_size = p->file_size;
-                                x->flags = MM_FLAG_R | MM_FLAG_W | MM_FLAG_X;
-                                x->valid = MM_VALID_ADDR | MM_VALID_SIZE | MM_VALID_FILE_OFFS | MM_VALID_FILE_SIZE;
-                            }
-                        }
-                    }
+                    program_headers_ranges(file, addr0, addr1, res, base_addr);
                 }
             }
         }