17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57a5d89c4Sab196087 * Common Development and Distribution License (the "License"). 67a5d89c4Sab196087 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23*6b1abd46SPeter Dennis - Sustaining Engineer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* Copyright (c) 1987, 1988 Microsoft Corporation */ 317c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <libelf.h> 367c478bd9Sstevel@tonic-gate #include "decl.h" 377c478bd9Sstevel@tonic-gate #include "msg.h" 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * Routines for generating a checksum for an elf image. Typically used to create 417c478bd9Sstevel@tonic-gate * a DT_CHECKSUM entry. This checksum is intended to remain constant after 427c478bd9Sstevel@tonic-gate * operations such as strip(1)/mcs(1), thus only allocatable sections are 437c478bd9Sstevel@tonic-gate * processed, and of those, any that might be modified by these external 447c478bd9Sstevel@tonic-gate * commands are skipped. 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate #define MSW(l) (((l) >> 16) & 0x0000ffffL) 477c478bd9Sstevel@tonic-gate #define LSW(l) ((l) & 0x0000ffffL) 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * update and epilogue sum functions (stolen from libcmd) 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate static long 547c478bd9Sstevel@tonic-gate sumupd(long sum, char *cp, unsigned long cnt) 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate if ((cp == 0) || (cnt == 0)) 577c478bd9Sstevel@tonic-gate return (sum); 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate while (cnt--) 607c478bd9Sstevel@tonic-gate sum += *cp++ & 0x00ff; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate return (sum); 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static long 667c478bd9Sstevel@tonic-gate sumepi(long sum) 677c478bd9Sstevel@tonic-gate { 687c478bd9Sstevel@tonic-gate long _sum; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate _sum = LSW(sum) + MSW(sum); 717c478bd9Sstevel@tonic-gate return ((ushort_t)(LSW(_sum) + MSW(_sum))); 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate 74*6b1abd46SPeter Dennis - Sustaining Engineer /* 75*6b1abd46SPeter Dennis - Sustaining Engineer * This module is compiled twice, the second time having 76*6b1abd46SPeter Dennis - Sustaining Engineer * -D_ELF64 defined. The following set of macros represent 77*6b1abd46SPeter Dennis - Sustaining Engineer * the differences between the two compilations. Be 78*6b1abd46SPeter Dennis - Sustaining Engineer * careful *not* to add any class dependent code (anything 79*6b1abd46SPeter Dennis - Sustaining Engineer * that has elf32 or elf64 in the name) to this code 80*6b1abd46SPeter Dennis - Sustaining Engineer * without hiding it behind a switchable macro like these. 81*6b1abd46SPeter Dennis - Sustaining Engineer */ 82*6b1abd46SPeter Dennis - Sustaining Engineer #if defined(_ELF64) 83*6b1abd46SPeter Dennis - Sustaining Engineer 84*6b1abd46SPeter Dennis - Sustaining Engineer #define elf_checksum elf64_checksum 85*6b1abd46SPeter Dennis - Sustaining Engineer #define Elf_Ehdr Elf64_Ehdr 86*6b1abd46SPeter Dennis - Sustaining Engineer #define Elf_Shdr Elf64_Shdr 87*6b1abd46SPeter Dennis - Sustaining Engineer #define getehdr elf64_getehdr 88*6b1abd46SPeter Dennis - Sustaining Engineer #define getshdr elf64_getshdr 89*6b1abd46SPeter Dennis - Sustaining Engineer 90*6b1abd46SPeter Dennis - Sustaining Engineer #else /* else ELF32 */ 91*6b1abd46SPeter Dennis - Sustaining Engineer 92*6b1abd46SPeter Dennis - Sustaining Engineer #define elf_checksum elf32_checksum 93*6b1abd46SPeter Dennis - Sustaining Engineer #define Elf_Ehdr Elf32_Ehdr 94*6b1abd46SPeter Dennis - Sustaining Engineer #define Elf_Shdr Elf32_Shdr 95*6b1abd46SPeter Dennis - Sustaining Engineer #define getehdr elf32_getehdr 96*6b1abd46SPeter Dennis - Sustaining Engineer #define getshdr elf32_getshdr 97*6b1abd46SPeter Dennis - Sustaining Engineer 98*6b1abd46SPeter Dennis - Sustaining Engineer #endif /* ELF64 */ 99*6b1abd46SPeter Dennis - Sustaining Engineer 1007c478bd9Sstevel@tonic-gate long 101*6b1abd46SPeter Dennis - Sustaining Engineer elf_checksum(Elf * elf) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate long sum = 0; 104*6b1abd46SPeter Dennis - Sustaining Engineer Elf_Ehdr * ehdr; 105*6b1abd46SPeter Dennis - Sustaining Engineer Elf_Shdr * shdr; 1067c478bd9Sstevel@tonic-gate Elf_Scn * scn; 1077c478bd9Sstevel@tonic-gate Elf_Data * data, * (* getdata)(Elf_Scn *, Elf_Data *); 1087c478bd9Sstevel@tonic-gate size_t shnum; 1097c478bd9Sstevel@tonic-gate 110*6b1abd46SPeter Dennis - Sustaining Engineer if ((ehdr = getehdr(elf)) == 0) 1117c478bd9Sstevel@tonic-gate return (0); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * Determine the data information to retrieve. When called from ld() 1157c478bd9Sstevel@tonic-gate * we're processing an ELF_C_IMAGE (memory) image and thus need to use 1167c478bd9Sstevel@tonic-gate * elf_getdata(), as there is not yet a file image (or raw data) backing 1177c478bd9Sstevel@tonic-gate * this. When called from utilities like elfdump(1) we're processing a 1187c478bd9Sstevel@tonic-gate * file image and thus using the elf_rawdata() allows the same byte 1197c478bd9Sstevel@tonic-gate * stream to be processed from different architectures - presently this 1207c478bd9Sstevel@tonic-gate * is irrelevant, as the checksum simply sums the data bytes, their 1217c478bd9Sstevel@tonic-gate * order doesn't matter. But being uncooked is slightly less overhead. 122d29b2c44Sab196087 * 123d29b2c44Sab196087 * If the file is writable, the raw data will not reflect any 124d29b2c44Sab196087 * changes made in the process, so the uncooked version is only 125d29b2c44Sab196087 * for readonly files. 1267c478bd9Sstevel@tonic-gate */ 127d29b2c44Sab196087 if ((elf->ed_myflags & (EDF_MEMORY | EDF_WRITE)) != 0) 1287c478bd9Sstevel@tonic-gate getdata = elf_getdata; 1297c478bd9Sstevel@tonic-gate else 1307c478bd9Sstevel@tonic-gate getdata = elf_rawdata; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate for (shnum = 1; shnum < ehdr->e_shnum; shnum++) { 1337c478bd9Sstevel@tonic-gate if ((scn = elf_getscn(elf, shnum)) == 0) 1347c478bd9Sstevel@tonic-gate return (0); 135*6b1abd46SPeter Dennis - Sustaining Engineer if ((shdr = getshdr(scn)) == 0) 1367c478bd9Sstevel@tonic-gate return (0); 1377c478bd9Sstevel@tonic-gate 1387a5d89c4Sab196087 /* Exclude strippable sections */ 1397c478bd9Sstevel@tonic-gate if (!(shdr->sh_flags & SHF_ALLOC)) 1407c478bd9Sstevel@tonic-gate continue; 1417c478bd9Sstevel@tonic-gate 1427a5d89c4Sab196087 /* 1437a5d89c4Sab196087 * Exclude allocable sections that can change: 1447a5d89c4Sab196087 * - The .dynsym section can contain section symbols 1457a5d89c4Sab196087 * that strip might remove. 1467a5d89c4Sab196087 * - The .dynamic section is modified by the setting of 1477a5d89c4Sab196087 * this checksum value. 148*6b1abd46SPeter Dennis - Sustaining Engineer * - The .SUNW_dof section uses ftok(3C), which returns 149*6b1abd46SPeter Dennis - Sustaining Engineer * different values, to define a key for the 150*6b1abd46SPeter Dennis - Sustaining Engineer * objects in that section. 1517a5d89c4Sab196087 */ 1527c478bd9Sstevel@tonic-gate if ((shdr->sh_type == SHT_DYNSYM) || 153*6b1abd46SPeter Dennis - Sustaining Engineer (shdr->sh_type == SHT_DYNAMIC) || 154*6b1abd46SPeter Dennis - Sustaining Engineer (shdr->sh_type == SHT_SUNW_dof)) 1557c478bd9Sstevel@tonic-gate continue; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate data = 0; 158*6b1abd46SPeter Dennis - Sustaining Engineer while ((data = (*getdata)(scn, data)) != 0) 1597c478bd9Sstevel@tonic-gate sum = sumupd(sum, data->d_buf, data->d_size); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate return (sumepi(sum)); 1637c478bd9Sstevel@tonic-gate } 164