Home | History | Annotate | Download | only in libunwindstack
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <sys/types.h>
     18 #include <unistd.h>
     19 
     20 #include <memory>
     21 #include <string>
     22 
     23 #include <unwindstack/Elf.h>
     24 #include <unwindstack/MapInfo.h>
     25 #include <unwindstack/Maps.h>
     26 #include <unwindstack/Memory.h>
     27 
     28 namespace unwindstack {
     29 
     30 Memory* MapInfo::CreateMemory(pid_t pid) {
     31   if (end <= start) {
     32     return nullptr;
     33   }
     34 
     35   elf_offset = 0;
     36 
     37   // First try and use the file associated with the info.
     38   if (!name.empty()) {
     39     // Fail on device maps.
     40     if (flags & MAPS_FLAGS_DEVICE_MAP) {
     41       return nullptr;
     42     }
     43 
     44     std::unique_ptr<MemoryFileAtOffset> file_memory(new MemoryFileAtOffset);
     45     uint64_t map_size;
     46     if (offset != 0) {
     47       // Only map in a piece of the file.
     48       map_size = end - start;
     49     } else {
     50       map_size = UINT64_MAX;
     51     }
     52     if (file_memory->Init(name, offset, map_size)) {
     53       // It's possible that a non-zero offset might not be pointing to
     54       // valid elf data. Check if this is a valid elf, and if not assume
     55       // that this was meant to incorporate the entire file.
     56       if (offset != 0 && !Elf::IsValidElf(file_memory.get())) {
     57         // Don't bother checking the validity that will happen on the elf init.
     58         if (file_memory->Init(name, 0)) {
     59           elf_offset = offset;
     60           return file_memory.release();
     61         }
     62         // Fall through if the init fails.
     63       } else {
     64         return file_memory.release();
     65       }
     66     }
     67   }
     68 
     69   Memory* memory = nullptr;
     70   if (pid == getpid()) {
     71     memory = new MemoryLocal();
     72   } else {
     73     memory = new MemoryRemote(pid);
     74   }
     75   return new MemoryRange(memory, start, end);
     76 }
     77 
     78 Elf* MapInfo::GetElf(pid_t pid, bool init_gnu_debugdata) {
     79   if (elf) {
     80     return elf;
     81   }
     82 
     83   elf = new Elf(CreateMemory(pid));
     84   if (elf->Init() && init_gnu_debugdata) {
     85     elf->InitGnuDebugdata();
     86   }
     87   // If the init fails, keep the elf around as an invalid object so we
     88   // don't try to reinit the object.
     89   return elf;
     90 }
     91 
     92 }  // namespace unwindstack
     93