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.util.List;
020
021/**
022 * Section of an executable file.
023 * 
024 * @author Emmanuel Bourg
025 * @since 1.0
026 */
027public class Section {
028    
029    private PEFile peFile;
030    private int baseOffset;
031
032    Section(PEFile peFile, int baseOffset) {
033        this.peFile = peFile;
034        this.baseOffset = baseOffset;
035    }
036
037    /**
038     * An 8-byte, null-padded UTF-8 encoded string. If the string is exactly
039     * 8 characters long, there is no terminating null. For longer names, this
040     * field contains a slash (/) that is followed by an ASCII representation
041     * of a decimal number that is an offset into the string table. Executable
042     * images do not use a string table and do not support section names longer
043     * than 8 characters. Long names in object files are truncated if they are
044     * emitted to an executable file.
045     */
046    public String getName() {
047        byte[] buffer = new byte[8];
048        peFile.read(buffer, baseOffset, 0);
049        String name = new String(buffer);
050        if (name.indexOf(0) != -1) {
051            name = name.substring(0, name.indexOf(0));
052        }
053        
054        return name;
055    }
056
057    /**
058     * The total size of the section when loaded into memory. If this value is 
059     * greater than SizeOfRawData, the section is zero-padded. This field is 
060     * valid only for executable images and should be set to zero for object files.
061     */
062    public long getVirtualSize() {
063        return peFile.readDWord(baseOffset, 8);
064    }
065
066    /**
067     * For executable images, the address of the first byte of the section
068     * relative to the image base when the section is loaded into memory.
069     * For object files, this field is the address of the first byte before
070     * relocation is applied; for simplicity, compilers should set this to zero.
071     * Otherwise, it is an arbitrary value that is subtracted from offsets
072     * during relocation.
073     */
074    public long getVirtualAddress() {
075        return peFile.readDWord(baseOffset, 12);
076    }
077
078    /**
079     * The size of the section (for object files) or the size of the initialized
080     * data on disk (for image files). For executable images, this must be a
081     * multiple of FileAlignment from the optional header. If this is less than
082     * VirtualSize, the remainder of the section is zero-filled. Because the
083     * SizeOfRawData field is rounded but the VirtualSize field is not, it is
084     * possible for SizeOfRawData to be greater than VirtualSize as well. When
085     * a section contains only uninitialized data, this field should be zero.
086     */
087    public long getSizeOfRawData() {
088        return peFile.readDWord(baseOffset, 16);
089    }
090
091    /**
092     * The file pointer to the first page of the section within the COFF file.
093     * For executable images, this must be a multiple of FileAlignment from the
094     * optional header. For object files, the value should be aligned on a 4 byte
095     * boundary for best performance. When a section contains only uninitialized
096     * data, this field should be zero.
097     */
098    public long getPointerToRawData() {
099        return peFile.readDWord(baseOffset, 20);
100    }
101
102    /**
103     * The file pointer to the beginning of relocation entries for the section.
104     * This is set to zero for executable images or if there are no relocations.
105     */
106    public long getPointerToRelocations() {
107        return peFile.readDWord(baseOffset, 24);
108    }
109
110    /**
111     * The file pointer to the beginning of line-number entries for the section.
112     * This is set to zero if there are no COFF line numbers. This value should 
113     * be zero for an image because COFF debugging information is deprecated.
114     */
115    public long getPointerToLineNumbers() {
116        return peFile.readDWord(baseOffset, 28);
117    }
118
119    /**
120     * The number of relocation entries for the section. This is set to zero
121     * for executable images.
122     */
123    public int getNumberOfRelocations() {
124        return peFile.readWord(baseOffset, 32);
125    }
126
127    /**
128     * The number of line-number entries for the section. This value should
129     * be zero for an image because COFF debugging information is deprecated.
130     */
131    public int getNumberOfLineNumbers() {
132        return peFile.readWord(baseOffset, 34);
133    }
134
135    /**
136     * The flags that describe the characteristics of the section.
137     */
138    public List<SectionFlag> getCharacteristics() {
139        return SectionFlag.getFlags((int) peFile.readDWord(baseOffset, 36));
140    }
141}