001/** 002 * Copyright 2012 Emmanuel Bourg 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package net.jsign.pe; 018 019import java.nio.charset.StandardCharsets; 020import java.util.List; 021 022/** 023 * Section of an executable file. 024 * 025 * @author Emmanuel Bourg 026 * @since 1.0 027 */ 028public class Section { 029 030 private final PEFile peFile; 031 private final int baseOffset; 032 033 Section(PEFile peFile, int baseOffset) { 034 this.peFile = peFile; 035 this.baseOffset = baseOffset; 036 } 037 038 /** 039 * An 8-byte, null-padded UTF-8 encoded string. If the string is exactly 040 * 8 characters long, there is no terminating null. For longer names, this 041 * field contains a slash (/) that is followed by an ASCII representation 042 * of a decimal number that is an offset into the string table. Executable 043 * images do not use a string table and do not support section names longer 044 * than 8 characters. Long names in object files are truncated if they are 045 * emitted to an executable file. 046 * 047 * @return the name of the section 048 */ 049 public String getName() { 050 byte[] buffer = new byte[8]; 051 peFile.read(buffer, baseOffset, 0); 052 String name = new String(buffer, StandardCharsets.UTF_8); 053 if (name.indexOf(0) != -1) { 054 name = name.substring(0, name.indexOf(0)); 055 } 056 057 return name; 058 } 059 060 /** 061 * The total size of the section when loaded into memory. If this value is 062 * greater than SizeOfRawData, the section is zero-padded. This field is 063 * valid only for executable images and should be set to zero for object files. 064 * 065 * @return the virtual size 066 */ 067 public long getVirtualSize() { 068 return peFile.readDWord(baseOffset, 8); 069 } 070 071 /** 072 * For executable images, the address of the first byte of the section 073 * relative to the image base when the section is loaded into memory. 074 * For object files, this field is the address of the first byte before 075 * relocation is applied; for simplicity, compilers should set this to zero. 076 * Otherwise, it is an arbitrary value that is subtracted from offsets 077 * during relocation. 078 * 079 * @return the section address relative to the image base address 080 */ 081 public long getVirtualAddress() { 082 return peFile.readDWord(baseOffset, 12); 083 } 084 085 /** 086 * The size of the section (for object files) or the size of the initialized 087 * data on disk (for image files). For executable images, this must be a 088 * multiple of FileAlignment from the optional header. If this is less than 089 * VirtualSize, the remainder of the section is zero-filled. Because the 090 * SizeOfRawData field is rounded but the VirtualSize field is not, it is 091 * possible for SizeOfRawData to be greater than VirtualSize as well. When 092 * a section contains only uninitialized data, this field should be zero. 093 * 094 * @return the size of the section 095 */ 096 public long getSizeOfRawData() { 097 return peFile.readDWord(baseOffset, 16); 098 } 099 100 /** 101 * The file pointer to the first page of the section within the COFF file. 102 * For executable images, this must be a multiple of FileAlignment from the 103 * optional header. For object files, the value should be aligned on a 4 byte 104 * boundary for best performance. When a section contains only uninitialized 105 * data, this field should be zero. 106 * 107 * @return the file pointer to the first page 108 */ 109 public long getPointerToRawData() { 110 return peFile.readDWord(baseOffset, 20); 111 } 112 113 /** 114 * The file pointer to the beginning of relocation entries for the section. 115 * This is set to zero for executable images or if there are no relocations. 116 * 117 * @return the file pointer to the beginning of relocation entries 118 */ 119 public long getPointerToRelocations() { 120 return peFile.readDWord(baseOffset, 24); 121 } 122 123 /** 124 * The file pointer to the beginning of line-number entries for the section. 125 * This is set to zero if there are no COFF line numbers. This value should 126 * be zero for an image because COFF debugging information is deprecated. 127 * 128 * @return the file pointer to the beginning of line-number entries 129 */ 130 public long getPointerToLineNumbers() { 131 return peFile.readDWord(baseOffset, 28); 132 } 133 134 /** 135 * The number of relocation entries for the section. This is set to zero 136 * for executable images. 137 * 138 * @return the number of relocation entries 139 */ 140 public int getNumberOfRelocations() { 141 return peFile.readWord(baseOffset, 32); 142 } 143 144 /** 145 * The number of line-number entries for the section. This value should 146 * be zero for an image because COFF debugging information is deprecated. 147 * 148 * @return the number of line-number entries 149 */ 150 public int getNumberOfLineNumbers() { 151 return peFile.readWord(baseOffset, 34); 152 } 153 154 /** 155 * The flags that describe the characteristics of the section. 156 * 157 * @return the characteristics flags 158 */ 159 public List<SectionFlag> getCharacteristics() { 160 return SectionFlag.getFlags((int) peFile.readDWord(baseOffset, 36)); 161 } 162}