00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <private.h>
00025
00026 #ifndef lint
00027 static const char rcsid[] = "@(#) $Id: checksum.c,v 1.1.1.1 2005/10/21 19:00:00 marcel Exp $";
00028 #endif
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 static int
00047 skip_section(Elf_Scn *scn, unsigned cls) {
00048 if (cls == ELFCLASS32) {
00049 Elf32_Shdr *shdr = &scn->s_shdr32;
00050
00051 if (!(shdr->sh_flags & SHF_ALLOC)) {
00052 return 1;
00053 }
00054 switch (shdr->sh_type) {
00055 case SHT_NULL:
00056 case SHT_NOBITS:
00057
00058 case SHT_DYNSYM:
00059 case SHT_DYNAMIC:
00060 return 1;
00061 }
00062 }
00063 #if __LIBELF64
00064 else if (cls == ELFCLASS64) {
00065 Elf64_Shdr *shdr = &scn->s_shdr64;
00066
00067 if (!(shdr->sh_flags & SHF_ALLOC)) {
00068 return 1;
00069 }
00070 switch (shdr->sh_type) {
00071 case SHT_NULL:
00072 case SHT_NOBITS:
00073
00074 case SHT_DYNSYM:
00075 case SHT_DYNAMIC:
00076 return 1;
00077 }
00078 }
00079 #endif
00080 else {
00081 seterr(ERROR_UNIMPLEMENTED);
00082 }
00083 return 0;
00084 }
00085
00086 static long
00087 add_bytes(unsigned char *ptr, size_t len) {
00088 long csum = 0;
00089
00090 while (len--) {
00091 csum += *ptr++;
00092 }
00093 return csum;
00094 }
00095
00096 static long
00097 _elf_csum(Elf *elf) {
00098 long csum = 0;
00099 Elf_Data *data;
00100 Elf_Scn *scn;
00101
00102 if (!elf->e_ehdr && !_elf_cook(elf)) {
00103
00104 return 0L;
00105 }
00106 seterr(0);
00107 for (scn = elf->e_scn_1; scn; scn = scn->s_link) {
00108 if (scn->s_index == SHN_UNDEF || skip_section(scn, elf->e_class)) {
00109 continue;
00110 }
00111 data = NULL;
00112 while ((data = elf_getdata(scn, data))) {
00113 if (data->d_size) {
00114 if (data->d_buf == NULL) {
00115 seterr(ERROR_NULLBUF);
00116 return 0L;
00117 }
00118 csum += add_bytes(data->d_buf, data->d_size);
00119 }
00120 }
00121 }
00122 if (_elf_errno) {
00123 return 0L;
00124 }
00125 csum = (csum & 0xffff) + ((csum >> 16) & 0xffff);
00126 if (csum > 0xffff) {
00127 csum -= 0xffff;
00128 }
00129 return csum;
00130 }
00131
00132 long
00133 elf32_checksum(Elf *elf) {
00134 if (elf) {
00135 if (elf->e_kind != ELF_K_ELF) {
00136 seterr(ERROR_NOTELF);
00137 }
00138 else if (elf->e_class != ELFCLASS32) {
00139 seterr(ERROR_CLASSMISMATCH);
00140 }
00141 else {
00142 return _elf_csum(elf);
00143 }
00144 }
00145 return 0L;
00146 }
00147
00148 #if __LIBELF64
00149
00150 long
00151 elf64_checksum(Elf *elf) {
00152 if (elf) {
00153 if (elf->e_kind != ELF_K_ELF) {
00154 seterr(ERROR_NOTELF);
00155 }
00156 else if (elf->e_class != ELFCLASS64) {
00157 seterr(ERROR_CLASSMISMATCH);
00158 }
00159 else {
00160 return _elf_csum(elf);
00161 }
00162 }
00163 return 0L;
00164 }
00165
00166 long
00167 gelf_checksum(Elf *elf) {
00168 if (elf) {
00169 if (elf->e_kind != ELF_K_ELF) {
00170 seterr(ERROR_NOTELF);
00171 }
00172 else if (!valid_class(elf->e_class)) {
00173 seterr(ERROR_UNKNOWN_CLASS);
00174 }
00175 else {
00176 return _elf_csum(elf);
00177 }
00178 }
00179 return 0L;
00180 }
00181
00182 #endif