17c10abb4a47139144de207433f630c4531f3835aElliott Hughes/* 27c10abb4a47139144de207433f630c4531f3835aElliott Hughes * Copyright (C) 2017 The Android Open Source Project 37c10abb4a47139144de207433f630c4531f3835aElliott Hughes * All rights reserved. 47c10abb4a47139144de207433f630c4531f3835aElliott Hughes * 57c10abb4a47139144de207433f630c4531f3835aElliott Hughes * Redistribution and use in source and binary forms, with or without 67c10abb4a47139144de207433f630c4531f3835aElliott Hughes * modification, are permitted provided that the following conditions 77c10abb4a47139144de207433f630c4531f3835aElliott Hughes * are met: 87c10abb4a47139144de207433f630c4531f3835aElliott Hughes * * Redistributions of source code must retain the above copyright 97c10abb4a47139144de207433f630c4531f3835aElliott Hughes * notice, this list of conditions and the following disclaimer. 107c10abb4a47139144de207433f630c4531f3835aElliott Hughes * * Redistributions in binary form must reproduce the above copyright 117c10abb4a47139144de207433f630c4531f3835aElliott Hughes * notice, this list of conditions and the following disclaimer in 127c10abb4a47139144de207433f630c4531f3835aElliott Hughes * the documentation and/or other materials provided with the 137c10abb4a47139144de207433f630c4531f3835aElliott Hughes * distribution. 147c10abb4a47139144de207433f630c4531f3835aElliott Hughes * 157c10abb4a47139144de207433f630c4531f3835aElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 167c10abb4a47139144de207433f630c4531f3835aElliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 177c10abb4a47139144de207433f630c4531f3835aElliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 187c10abb4a47139144de207433f630c4531f3835aElliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 197c10abb4a47139144de207433f630c4531f3835aElliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 207c10abb4a47139144de207433f630c4531f3835aElliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 217c10abb4a47139144de207433f630c4531f3835aElliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 227c10abb4a47139144de207433f630c4531f3835aElliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 237c10abb4a47139144de207433f630c4531f3835aElliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 247c10abb4a47139144de207433f630c4531f3835aElliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 257c10abb4a47139144de207433f630c4531f3835aElliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267c10abb4a47139144de207433f630c4531f3835aElliott Hughes * SUCH DAMAGE. 277c10abb4a47139144de207433f630c4531f3835aElliott Hughes */ 287c10abb4a47139144de207433f630c4531f3835aElliott Hughes 297c10abb4a47139144de207433f630c4531f3835aElliott Hughes#include <gtest/gtest.h> 307c10abb4a47139144de207433f630c4531f3835aElliott Hughes 317c10abb4a47139144de207433f630c4531f3835aElliott Hughes#include <link.h> 327c10abb4a47139144de207433f630c4531f3835aElliott Hughes 337c10abb4a47139144de207433f630c4531f3835aElliott HughesTEST(link, dl_iterate_phdr_early_exit) { 347c10abb4a47139144de207433f630c4531f3835aElliott Hughes static size_t call_count = 0; 357c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_EQ(123, dl_iterate_phdr([](dl_phdr_info*, size_t, void*) { ++call_count; return 123; }, 367c10abb4a47139144de207433f630c4531f3835aElliott Hughes nullptr)); 377c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_EQ(1u, call_count); 387c10abb4a47139144de207433f630c4531f3835aElliott Hughes} 397c10abb4a47139144de207433f630c4531f3835aElliott Hughes 407c10abb4a47139144de207433f630c4531f3835aElliott HughesTEST(link, dl_iterate_phdr) { 417c10abb4a47139144de207433f630c4531f3835aElliott Hughes struct Functor { 427c10abb4a47139144de207433f630c4531f3835aElliott Hughes static int Callback(dl_phdr_info* i, size_t s, void* data) { 437c10abb4a47139144de207433f630c4531f3835aElliott Hughes reinterpret_cast<Functor*>(data)->DoChecks(i, s); 447c10abb4a47139144de207433f630c4531f3835aElliott Hughes return 0; 457c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 467c10abb4a47139144de207433f630c4531f3835aElliott Hughes void DoChecks(dl_phdr_info* info, size_t s) { 477c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_EQ(sizeof(dl_phdr_info), s); 487c10abb4a47139144de207433f630c4531f3835aElliott Hughes 497c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_TRUE(info->dlpi_name != nullptr); 507c10abb4a47139144de207433f630c4531f3835aElliott Hughes 517c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Find the first PT_LOAD program header so we can find the ELF header. 527c10abb4a47139144de207433f630c4531f3835aElliott Hughes for (ElfW(Half) i = 0; i < info->dlpi_phnum; ++i) { 537c10abb4a47139144de207433f630c4531f3835aElliott Hughes const ElfW(Phdr)* phdr = reinterpret_cast<const ElfW(Phdr)*>(&info->dlpi_phdr[i]); 547c10abb4a47139144de207433f630c4531f3835aElliott Hughes if (phdr->p_type == PT_LOAD) { 557c10abb4a47139144de207433f630c4531f3835aElliott Hughes const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(info->dlpi_addr + 567c10abb4a47139144de207433f630c4531f3835aElliott Hughes phdr->p_vaddr); 577c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Does it look like an ELF file? 587c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_EQ(0, memcmp(ehdr, ELFMAG, SELFMAG)); 597c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Does the e_phnum match what dl_iterate_phdr told us? 607c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_EQ(info->dlpi_phnum, ehdr->e_phnum); 617c10abb4a47139144de207433f630c4531f3835aElliott Hughes break; 627c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 637c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 647c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 657c10abb4a47139144de207433f630c4531f3835aElliott Hughes size_t count; 667c10abb4a47139144de207433f630c4531f3835aElliott Hughes } f = {}; 677c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_EQ(0, dl_iterate_phdr(Functor::Callback, &f)); 687c10abb4a47139144de207433f630c4531f3835aElliott Hughes} 697c10abb4a47139144de207433f630c4531f3835aElliott Hughes 707c10abb4a47139144de207433f630c4531f3835aElliott Hughes#if __arm__ 717c10abb4a47139144de207433f630c4531f3835aElliott Hughesstatic uintptr_t read_exidx_func(uintptr_t* entry) { 727c10abb4a47139144de207433f630c4531f3835aElliott Hughes int32_t offset = *entry; 737c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Sign-extend from int31 to int32. 747c10abb4a47139144de207433f630c4531f3835aElliott Hughes if ((offset & 0x40000000) != 0) { 757c10abb4a47139144de207433f630c4531f3835aElliott Hughes offset += -0x7fffffff - 1; 767c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 777c10abb4a47139144de207433f630c4531f3835aElliott Hughes return reinterpret_cast<uintptr_t>(entry) + offset; 787c10abb4a47139144de207433f630c4531f3835aElliott Hughes} 797c10abb4a47139144de207433f630c4531f3835aElliott Hughes__attribute__((__unused__)) static void another_function_in_same_ELF_file() {} 807c10abb4a47139144de207433f630c4531f3835aElliott Hughes#endif 817c10abb4a47139144de207433f630c4531f3835aElliott Hughes 827c10abb4a47139144de207433f630c4531f3835aElliott HughesTEST(link, dl_unwind_find_exidx) { 837c10abb4a47139144de207433f630c4531f3835aElliott Hughes#if __arm__ 847c10abb4a47139144de207433f630c4531f3835aElliott Hughes int count = 0; 857c10abb4a47139144de207433f630c4531f3835aElliott Hughes struct eit_entry_t { 867c10abb4a47139144de207433f630c4531f3835aElliott Hughes uintptr_t one; 877c10abb4a47139144de207433f630c4531f3835aElliott Hughes uintptr_t two; 887c10abb4a47139144de207433f630c4531f3835aElliott Hughes }; 897c10abb4a47139144de207433f630c4531f3835aElliott Hughes eit_entry_t* entries = reinterpret_cast<eit_entry_t*>(dl_unwind_find_exidx( 907c10abb4a47139144de207433f630c4531f3835aElliott Hughes reinterpret_cast<_Unwind_Ptr>(read_exidx_func), &count)); 917c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_TRUE(entries != nullptr); 927c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_GT(count, 0); 937c10abb4a47139144de207433f630c4531f3835aElliott Hughes 947c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Sanity checks 957c10abb4a47139144de207433f630c4531f3835aElliott Hughes uintptr_t func = reinterpret_cast<uintptr_t>(read_exidx_func); 967c10abb4a47139144de207433f630c4531f3835aElliott Hughes bool found = false; 977c10abb4a47139144de207433f630c4531f3835aElliott Hughes for (int i = 0; i < count; ++i) { 987c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Entries must have bit 31 clear. 997c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_TRUE((entries[i].one & (1<<31)) == 0); 1007c10abb4a47139144de207433f630c4531f3835aElliott Hughes 1017c10abb4a47139144de207433f630c4531f3835aElliott Hughes uintptr_t exidx_func = read_exidx_func(&entries[i].one); 1027c10abb4a47139144de207433f630c4531f3835aElliott Hughes 1037c10abb4a47139144de207433f630c4531f3835aElliott Hughes // If our function is compiled for thumb, exception table contains our address - 1. 1047c10abb4a47139144de207433f630c4531f3835aElliott Hughes if (func == exidx_func || func == exidx_func + 1) found = true; 1057c10abb4a47139144de207433f630c4531f3835aElliott Hughes 1067c10abb4a47139144de207433f630c4531f3835aElliott Hughes // Entries must be sorted. Some addresses may appear twice if function 1077c10abb4a47139144de207433f630c4531f3835aElliott Hughes // is compiled for arm. 1087c10abb4a47139144de207433f630c4531f3835aElliott Hughes if (i > 0) { 1097c10abb4a47139144de207433f630c4531f3835aElliott Hughes EXPECT_GE(exidx_func, read_exidx_func(&entries[i - 1].one)) << i; 1107c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 1117c10abb4a47139144de207433f630c4531f3835aElliott Hughes } 1127c10abb4a47139144de207433f630c4531f3835aElliott Hughes ASSERT_TRUE(found); 1137c10abb4a47139144de207433f630c4531f3835aElliott Hughes#else 1147c10abb4a47139144de207433f630c4531f3835aElliott Hughes GTEST_LOG_(INFO) << "dl_unwind_find_exidx is an ARM-only API\n"; 1157c10abb4a47139144de207433f630c4531f3835aElliott Hughes#endif 1167c10abb4a47139144de207433f630c4531f3835aElliott Hughes} 117