1/* 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26#include <stdio.h> 27#include <sys/mman.h> 28#include <dlfcn.h> 29#include <libelf.h> 30#include <strings.h> 31#include <fcntl.h> 32#include <sys/param.h> 33#include <stdlib.h> 34#include <thread.h> 35#include <synch.h> 36#include <stdarg.h> 37 38#define TRUE 1 39#define FALSE 0 40 41 42static void fail(const char *err, ...) 43{ 44 va_list ap; 45 va_start(ap, err); 46 vfprintf(stderr, err, ap); 47 fflush(stderr); 48 va_end(ap); 49 exit(2); 50} 51 52 53static Elf_Scn *find_section(Elf *elf, Elf_Data *sectionStringData, 54 const char *name) 55{ 56 Elf_Scn *result = NULL; 57 Elf32_Shdr *symHeader; 58 const char *p; 59 60 while ((result = elf_nextscn(elf, result)) != NULL) { 61 symHeader = elf32_getshdr(result); 62 p = (const char *)(sectionStringData->d_buf) + symHeader->sh_name; 63 if (strcmp(p, name) == 0) 64 break; 65 } 66 return result; 67} 68 69 70static void trash_mcount(int count, Elf_Data *data, Elf_Data *stringData) 71{ 72 int i; 73 for (i = 0; i < count; ++i) { 74 Elf32_Sym *sym = ((Elf32_Sym *)data->d_buf) + i; 75 char *name = (char *)stringData->d_buf + sym->st_name; 76 77 if (strcmp(name, "_mcount") == 0) { 78 name[6] = 'T'; 79 break; 80 } 81 } 82 if (i < count) 83 printf("Symbol _mcount found and changed.\n"); 84 else 85 printf("Symbol _mcount not found.\n"); 86} 87 88 89/* 90 * In the executable program named as the sole command line argument, find 91 * the symbol _mcount, if present, and change its name to something 92 * different. The symbol _mcount is included in Solaris/x86 programs by 93 * the compilers, and its presence prevents preloaded modules from 94 * supplying a custom implementation of that method. 95 */ 96 97int main(int argc, char **argv) 98{ 99 Elf32_Ehdr *ehdr; 100 Elf_Scn *sectionStringSection; 101 Elf_Scn *stringSection; 102 Elf_Scn *dynStringSection; 103 Elf_Scn *symSection; 104 Elf_Scn *dynSymSection; 105 Elf32_Shdr *symHeader; 106 Elf32_Shdr *dynSymHeader; 107 Elf32_Shdr *dynStringHeader; 108 Elf32_Shdr *stringHeader; 109 Elf *elf; 110 const char *p; 111 int i; 112 const char *fullName; 113 int fd; 114 Elf_Data *sectionStringData; 115 Elf_Data *symData; 116 Elf_Data *dynSymData; 117 Elf_Data *symStringData; 118 Elf_Data *dynSymStringData; 119 int symCount; 120 int dynSymCount; 121 122 123 if (argc != 2) { 124 fprintf(stderr, "Usage:\n" 125 "\t%s <file>\n", argv[0]); 126 exit(1); 127 } 128 129 fullName = argv[1]; 130 131 /* Open the ELF file. Get section headers. */ 132 133 elf_version(EV_CURRENT); 134 fd = open(fullName, O_RDWR); 135 if (fd < 0) 136 fail("Unable to open ELF file %s.\n", fullName); 137 elf = elf_begin(fd, ELF_C_RDWR, (Elf *)0); 138 if (elf == NULL) 139 fail("elf_begin failed.\n"); 140 ehdr = elf32_getehdr(elf); 141 sectionStringSection = elf_getscn(elf, ehdr->e_shstrndx); 142 sectionStringData = elf_getdata(sectionStringSection, NULL); 143 144 /* Find the symbol table section. */ 145 146 symSection = find_section(elf, sectionStringData, ".symtab"); 147 if (symSection != NULL) { 148 symData = elf_getdata(symSection, NULL); 149 symCount = symData->d_size / sizeof (Elf32_Sym); 150 151 /* Find the string section, trash the _mcount symbol. */ 152 153 stringSection = find_section(elf, sectionStringData, ".strtab"); 154 if (stringSection == NULL) 155 fail("Unable to find string table.\n"); 156 symStringData = elf_getdata(stringSection, NULL); 157 trash_mcount(symCount, symData, symStringData); 158 } else { 159 fprintf(stderr, "Unable to find symbol table.\n"); 160 } 161 162 /* Find the dynamic symbol table section. */ 163 164 dynSymSection = find_section(elf, sectionStringData, ".dynsym"); 165 if (dynSymSection != NULL) { 166 dynSymData = elf_getdata(dynSymSection, NULL); 167 dynSymCount = dynSymData->d_size / sizeof (Elf32_Sym); 168 169 /* Find the dynamic string section, trash the _mcount symbol. */ 170 171 dynStringSection = find_section(elf, sectionStringData, ".dynstr"); 172 if (dynStringSection == NULL) 173 fail("Unable to find dynamic string table.\n"); 174 dynSymStringData = elf_getdata(dynStringSection, NULL); 175 trash_mcount(dynSymCount, dynSymData, dynSymStringData); 176 } else { 177 fail("Unable to find dynamic symbol table.\n"); 178 } 179 180 elf_update(elf, ELF_C_WRITE); 181 elf_end(elf); 182 183 exit(0); 184} 185