1 /*
   2  * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jdk.tools.jaotc.binformat.elf;
  25 
  26 import java.nio.ByteBuffer;
  27 import java.nio.ByteOrder;
  28 
  29 import jdk.tools.jaotc.binformat.elf.Elf;
  30 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
  31 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
  32 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
  33 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
  34 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
  35 import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;
  36 
  37 public class ElfSection {
  38     String name;
  39     ByteBuffer section;
  40     byte [] data;
  41     boolean hasrelocations;
  42     int sectionIndex;
  43 
  44     /**
  45      * String holding section name strings
  46      */
  47     private static StringBuilder sectNameTab = new StringBuilder();
  48 
  49     /**
  50      * Keeps track of bytes in section string table since strTabContent.length()
  51      * is number of chars, not bytes.
  52      */
  53     private static int shStrTabNrOfBytes = 0;
  54 
  55     public ElfSection(String sectName, byte [] sectData, int sectFlags,
  56                       int sectType, boolean hasRelocations, int sectIndex) {
  57 
  58         long align;
  59 
  60         section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize);
  61 
  62         // Return all 0's for NULL section
  63         if (sectIndex == 0) {
  64             sectNameTab.append('\0');
  65             shStrTabNrOfBytes += 1;
  66             data = null;
  67             hasrelocations = false;
  68             sectionIndex = 0;
  69             return;
  70         }
  71 
  72         section.putInt(Elf64_Shdr.sh_name.off, shStrTabNrOfBytes);
  73         sectNameTab.append(sectName).append('\0');
  74         shStrTabNrOfBytes += (sectName.getBytes().length + 1);
  75         name = sectName;
  76 
  77         section.putInt(Elf64_Shdr.sh_type.off, sectType);
  78         section.putLong(Elf64_Shdr.sh_flags.off, sectFlags);
  79         section.putLong(Elf64_Shdr.sh_addr.off, 0);
  80         section.putLong(Elf64_Shdr.sh_offset.off, 0);
  81 
  82         if (sectName.equals(".shstrtab")) {
  83             section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes);
  84             data = sectNameTab.toString().getBytes();
  85         }
  86         else {
  87             data = sectData;
  88             section.putLong(Elf64_Shdr.sh_size.off, sectData.length);
  89         }
  90 
  91         section.putLong(Elf64_Shdr.sh_entsize.off, 0);
  92 
  93         // Determine the alignment and entrysize
  94         // based on type of section
  95         switch (sectType) {
  96             case Elf64_Shdr.SHT_PROGBITS:
  97                 if ((sectFlags & Elf64_Shdr.SHF_EXECINSTR) != 0)
  98                     align = 16;
  99                 else
 100                     align = 4;
 101                 break;
 102             case Elf64_Shdr.SHT_SYMTAB:
 103                 align = 8;
 104                 section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize);
 105                 break;
 106             case Elf64_Shdr.SHT_STRTAB:
 107                 align = 1;
 108                 break;
 109             case Elf64_Shdr.SHT_RELA:
 110                 align = 8;
 111                 section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize);
 112                 break;
 113             case Elf64_Shdr.SHT_REL:
 114                 align = 8;
 115                 section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize);
 116                 break;
 117             case Elf64_Shdr.SHT_NOBITS:
 118                 align = 4;
 119                 break;
 120             default:
 121                 align = 8;
 122                 break;
 123         }
 124         section.putLong(Elf64_Shdr.sh_addralign.off, align);
 125 
 126         hasrelocations = hasRelocations;
 127         sectionIndex = sectIndex;
 128     }
 129 
 130     public String getName() {
 131         return name;
 132     }
 133 
 134     public long getSize() {
 135         return section.getLong(Elf64_Shdr.sh_size.off);
 136     }
 137 
 138     public int getDataAlign() {
 139         return ((int)section.getLong(Elf64_Shdr.sh_addralign.off));
 140     }
 141 
 142     // Alignment requirements for the Elf64_Shdr structures
 143     public static int getShdrAlign() {
 144         return (4);
 145     }
 146 
 147     public byte[] getArray() {
 148         return section.array();
 149     }
 150 
 151     public byte[] getDataArray() {
 152         return data;
 153     }
 154 
 155     public void setOffset(long offset) {
 156         section.putLong(Elf64_Shdr.sh_offset.off, offset);
 157     }
 158 
 159     public void setLink(int link) {
 160         section.putInt(Elf64_Shdr.sh_link.off, link);
 161     }
 162 
 163     public void setInfo(int info) {
 164         section.putInt(Elf64_Shdr.sh_info.off, info);
 165     }
 166 
 167     public long getOffset() {
 168         return (section.getLong(Elf64_Shdr.sh_offset.off));
 169     }
 170 
 171     public boolean hasRelocations() {
 172         return hasrelocations;
 173     }
 174 
 175     public int getSectionId() {
 176         return sectionIndex;
 177     }
 178 
 179 }
 180 
 181