//-------------------------------------------------------------------------------------------------- // // @ CopyRight Roberti & Parau Enterprises, Inc. 2021-2023 // // This work is licensed under the Creative Commons Attribution-NoDerivatives 4.0 International License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-nd/4.0/ // or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. // //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- // // Class to manage code Sections/MMaps // //-------------------------------------------------------------------------------------------------- package framework; import java.math.BigInteger; import java.util.*; public class DVSections { protected DVSections(DVStatements statements, DVSymbols symbols) { this.statements= statements; this.symbols= symbols; } // // Create a new section // protected Section startSection(DVStatements.Statement owner, Token label, SectionType type) { return new Section(owner, label, type); } // // Section inner class // public class Section { protected Section(DVStatements.Statement owner, Token label, SectionType type) { this.name= label; this.owner= owner; this.type= type; this.resetExpression= new DVExpression(this.owner); this.owner.ownerSection= this; this.owner.symbol.valueExpression= DVExpression.getOffsetConstantExpression(owner, this, BigInteger.ZERO); this.owner.symbol.replExpression= DVExpression.getConstantExpression(BigInteger.ONE, owner); DVSections.this.sectionMap.put(this.name.image, this); DVSections.this.currSection= this; this.owner.sectionIndex= this.addStatement(this.owner); } // // Set attributes // protected void setAttributes(BigInteger typeValue, BigInteger attributeValue, BigInteger alignValue, String externalName) { this.typeValue= typeValue; this.attributeValue= attributeValue; if (this.alignValue.compareTo(alignValue) < 0) this.alignValue= alignValue; if ((this.externalName= externalName) == null) this.externalName= this.name.image; } // // Add a statement // protected int addStatement(DVStatements.Statement statement) { this.statementList.add(statement); return this.statementList.size(); } // // Get next statement // protected DVStatements.Statement getNextStatement(int index) { if (index >= this.statementList.size() || index < -1) return null; return this.statementList.get(index+1); } // // Get previous statement // protected DVStatements.Statement getPrevStatement(int index) { if (index >= this.statementList.size()+1 || index < 1) return null; return this.statementList.get(index-1); } // // Clear all relocation // protected void clearRelocation() { this.relocationList.clear(); } // // Add a relocation record // protected void addRelocation(DVStatements.Statement owner, DVSymbols.Symbol symbol, BigInteger offset, BigInteger addEnd, DVAbi.RelocationID relocationID) { if (owner.ownerSection.typeValue.equals(DVUtil.sectionTypeNobits) || this.type == SectionType.MMAP) { owner.putError("A relocation cannot be added to an MMAP or an ELF section marked with type NOBITS"); return; } if (! symbol.isExternal && ! symbol.isCommon) { if (symbol.owner == null ) { owner.putError("Symbol [" + symbol.name + "] is not EXTERNAL nor COMMON and has not been defined"); return; } if (symbol.owner.ownerSection.type == SectionType.MMAP) { owner.putError("Symbol [" + symbol.name + "] cannot be marked locally exported - it is defined in a MMAP"); return; } if (! symbol.isExported && ! symbol.isExternal && ! symbol.isCommon) symbol.setLocalExport(); } this.relocationList.add(new Relocation(symbol, offset, addEnd, relocationID)); } // // Relocation inner class // public class Relocation { private Relocation(DVSymbols.Symbol symbol, BigInteger offset, BigInteger addEnd, DVAbi.RelocationID relocationID) { this.symbol= symbol; this.offset= offset; this.addEnd= addEnd; this.relocationID= relocationID; } protected final DVSymbols.Symbol symbol; protected final BigInteger offset; protected final BigInteger addEnd; protected final DVAbi.RelocationID relocationID; } // // Getter methods // public DVStatements.Statement getOwner() { return this.owner; } public String getName() { return this.name.image; } public SectionType getSectionType() { return this.type; } // // Reset section for a new code generation cycle // protected void resetSection() { this.resetExpression= new DVExpression(this.owner); this.relocationList.clear(); } // // Class fields // protected final Token name; protected String externalName= null; protected final DVStatements.Statement owner; protected SectionType type= SectionType.NONE; protected BigInteger attributeValue; protected BigInteger typeValue; protected BigInteger alignValue= BigInteger.ZERO; protected DVExpression lengthExpression; protected int size; protected DVSectionTable.ElfSection elfSection; protected DVExpression resetExpression; protected final ArrayList relocationList= new ArrayList(); protected final ArrayList statementList= new ArrayList(); } // // Set symbol in section based on offset, length and repl of // preceding symbol // protected void setNextSymbolValueExpression(DVStatements.Statement newStatement) { newStatement.sectionIndex= DVSections.this.currSection.addStatement(newStatement); if (newStatement.symbol.valueExpression == null) newStatement.symbol.valueExpression= DVExpression.getNewSymbolValueExpression( this.currSection.statementList.get(this.currSection.statementList.size()-2).symbol, newStatement.symbol); } // // Set counter // protected void setCounter(DVStatements.Statement newStatement) { this.currSection.resetExpression.maxExpression(DVExpression.getEndValueExpression( this.currSection.statementList.get(this.currSection.statementList.size()-1))); } // // Reset counter // protected DVExpression resetCounter() { DVExpression expr= this.currSection.resetExpression.maxExpression(DVExpression.getEndValueExpression( this.currSection.statementList.get(this.currSection.statementList.size()-1))); this.currSection.resetExpression= new DVExpression(this.currSection.owner); return expr; } // // Set section expression length // protected void setExpressionLength() { if (this.currSection == null) return; this.currSection.lengthExpression= this.resetCounter(); } // // Generate binary for each section // protected byte[] buildBinaries(DVSectionTable sectionTable) { for (Map.Entry e : this.sectionMap.entrySet()) { Section s= e.getValue(); s.size= s.lengthExpression.evaluate(false).intConstant.intValue(); if (s.type != SectionType.SECTION) continue; s.elfSection= sectionTable.startSection(s.externalName, s.typeValue, s.attributeValue, s.alignValue, s.size); for (int i= 1; i < s.statementList.size(); i++) { DVStatements.Statement t= s.statementList.get(i); if (t.genCode == null || t.genCode.code == null) continue; s.elfSection.copyBytes(t.genCode.code, t.symbol.resultValue.intConstant.intValue()); } if (s.relocationList.isEmpty()) continue; s.elfSection.addRelocationSection(s.relocationList); } return null; } protected void resetSections() { for (Map.Entry e : this.sectionMap.entrySet()) e.getValue().resetSection(); } // // Class fields // protected final DVStatements statements; protected final DVSymbols symbols; protected Section currSection= null; protected final LinkedHashMap sectionMap= new LinkedHashMap(); // // Section type // public enum SectionType { MMAP, SECTION, NONE } }