1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 31 /* All Rights Reserved */ 32 33 #pragma ident "%Z%%M% %I% %E% SMI" 34 35 #include "syn.h" 36 #include <errno.h> 37 #include <libelf.h> 38 #include "decl.h" 39 #include "msg.h" 40 41 /* 42 * Routines for generating a checksum for an elf image. Typically used to create 43 * a DT_CHECKSUM entry. This checksum is intended to remain constant after 44 * operations such as strip(1)/mcs(1), thus only allocatable sections are 45 * processed, and of those, any that might be modified by these external 46 * commands are skipped. 47 */ 48 #define MSW(l) (((l) >> 16) & 0x0000ffffL) 49 #define LSW(l) ((l) & 0x0000ffffL) 50 51 52 /* 53 * update and epilogue sum functions (stolen from libcmd) 54 */ 55 static long 56 sumupd(long sum, char *cp, unsigned long cnt) 57 { 58 if ((cp == 0) || (cnt == 0)) 59 return (sum); 60 61 while (cnt--) 62 sum += *cp++ & 0x00ff; 63 64 return (sum); 65 } 66 67 static long 68 sumepi(long sum) 69 { 70 long _sum; 71 72 _sum = LSW(sum) + MSW(sum); 73 return ((ushort_t)(LSW(_sum) + MSW(_sum))); 74 } 75 76 long 77 elf32_checksum(Elf * elf) 78 { 79 long sum = 0; 80 Elf32_Ehdr * ehdr; 81 Elf32_Shdr * shdr; 82 Elf_Scn * scn; 83 Elf_Data * data, * (* getdata)(Elf_Scn *, Elf_Data *); 84 size_t shnum; 85 86 if ((ehdr = elf32_getehdr(elf)) == 0) 87 return (0); 88 89 /* 90 * Determine the data information to retrieve. When called from ld() 91 * we're processing an ELF_C_IMAGE (memory) image and thus need to use 92 * elf_getdata(), as there is not yet a file image (or raw data) backing 93 * this. When called from utilities like elfdump(1) we're processing a 94 * file image and thus using the elf_rawdata() allows the same byte 95 * stream to be processed from different architectures - presently this 96 * is irrelevant, as the checksum simply sums the data bytes, their 97 * order doesn't matter. But being uncooked is slightly less overhead. 98 */ 99 if (elf->ed_myflags & EDF_MEMORY) 100 getdata = elf_getdata; 101 else 102 getdata = elf_rawdata; 103 104 for (shnum = 1; shnum < ehdr->e_shnum; shnum++) { 105 if ((scn = elf_getscn(elf, shnum)) == 0) 106 return (0); 107 if ((shdr = elf32_getshdr(scn)) == 0) 108 return (0); 109 110 if (!(shdr->sh_flags & SHF_ALLOC)) 111 continue; 112 113 if ((shdr->sh_type == SHT_DYNSYM) || 114 (shdr->sh_type == SHT_DYNAMIC)) 115 continue; 116 117 data = 0; 118 while ((data = (*getdata)(scn, data)) != 0) 119 sum = sumupd(sum, data->d_buf, data->d_size); 120 121 } 122 return (sumepi(sum)); 123 } 124 125 long 126 elf64_checksum(Elf * elf) 127 { 128 long sum = 0; 129 Elf64_Ehdr * ehdr; 130 Elf64_Shdr * shdr; 131 Elf_Scn * scn; 132 Elf_Data * data; 133 size_t shnum; 134 135 if ((ehdr = elf64_getehdr(elf)) == 0) 136 return (0); 137 138 for (shnum = 1; shnum < ehdr->e_shnum; shnum++) { 139 if ((scn = elf_getscn(elf, shnum)) == 0) 140 return (0); 141 if ((shdr = elf64_getshdr(scn)) == 0) 142 return (0); 143 144 if (!(shdr->sh_flags & SHF_ALLOC)) 145 continue; 146 147 if ((shdr->sh_type == SHT_DYNSYM) || 148 (shdr->sh_type == SHT_DYNAMIC)) 149 continue; 150 151 data = 0; 152 while ((data = elf_getdata(scn, data)) != 0) 153 sum = sumupd(sum, data->d_buf, data->d_size); 154 155 } 156 return (sumepi(sum)); 157 } 158