Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for PowerPCEabiGcc #45

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
}
```

Valid values for `parserType` are `GCC` and `TI`. Valid values for `scale` are `DEFAULT`, `KILO`, `MEGA` and `GIGA`.
Valid values for `parserType` are `GCC`, 'PowerPCEabiGcc' and `TI`. Valid values for `scale` are `DEFAULT`, `KILO`, `MEGA` and `GIGA`.

```
job ('mmap_GEN'){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import static javaposse.jobdsl.plugin.ContextExtensionPoint.executeInContext;
import net.praqma.jenkins.memorymap.parser.AbstractMemoryMapParser;
import net.praqma.jenkins.memorymap.parser.gcc.GccMemoryMapParser;
import net.praqma.jenkins.memorymap.parser.powerpceabigcc.PowerPCEabiGccMemoryMapParser;
import net.praqma.jenkins.memorymap.parser.ti.TexasInstrumentsMemoryMapParser;

public class MemoryMapJobDslContext implements Context {
Expand Down Expand Up @@ -46,7 +47,7 @@ public void scale(String value) {
}

List<AbstractMemoryMapParser> parsers = new ArrayList<>();
List<String> parserTypes = Arrays.asList("GCC", "TI");
List<String> parserTypes = Arrays.asList("GCC", "PowerPCEabiGcc", "TI");

public void parser(String parserType, String parserUniqueName, String commandFile, String mapFile, Runnable closure) {
checkArgument(parserTypes.contains(parserType), "Parser type must be one of " + parserTypes);
Expand All @@ -58,6 +59,9 @@ public void parser(String parserType, String parserUniqueName, String commandFil
case "GCC":
parser = new GccMemoryMapParser(parserUniqueName, mapFile, commandFile, wordSize, showBytesOnGraphs, context.graphConfigurations);
break;
case "PowerPCEabiGcc":
parser = new PowerPCEabiGccMemoryMapParser(parserUniqueName, mapFile, commandFile, wordSize, showBytesOnGraphs, context.graphConfigurations);
break;
case "TI":
parser = new TexasInstrumentsMemoryMapParser(parserUniqueName, mapFile, commandFile, wordSize, context.graphConfigurations, showBytesOnGraphs);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import net.praqma.jenkins.memorymap.graph.MemoryMapGraphConfiguration;
import net.praqma.jenkins.memorymap.graph.MemoryMapGraphConfigurationDescriptor;
import net.praqma.jenkins.memorymap.parser.gcc.GccMemoryMapParser;
import net.praqma.jenkins.memorymap.parser.powerpceabigcc.PowerPCEabiGccMemoryMapParser;
import net.praqma.jenkins.memorymap.parser.ti.TexasInstrumentsMemoryMapParser;
import net.praqma.jenkins.memorymap.result.MemoryMapConfigMemory;
import org.apache.commons.collections.ListUtils;
Expand All @@ -63,6 +64,8 @@
@JsonSubTypes({
@Type(value = TexasInstrumentsMemoryMapParser.class, name = "TexasInstrumentsMemoryMapParser")
,
@Type(value = PowerPCEabiGccMemoryMapParser.class, name = "PowerPCEabiGccMemoryMapParser")
,
@Type(value = GccMemoryMapParser.class, name = "GccMemoryMapParser")})

public abstract class AbstractMemoryMapParser implements Describable<AbstractMemoryMapParser>, ExtensionPoint, Serializable {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
package net.praqma.jenkins.memorymap.parser.powerpceabigcc;

import hudson.AbortException;
import hudson.Extension;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.praqma.jenkins.memorymap.graph.MemoryMapGraphConfiguration;
import net.praqma.jenkins.memorymap.parser.AbstractMemoryMapParser;
import net.praqma.jenkins.memorymap.parser.MemoryMapParserDescriptor;
import net.praqma.jenkins.memorymap.result.MemoryMapConfigMemory;
import net.praqma.jenkins.memorymap.result.MemoryMapConfigMemoryItem;
import net.praqma.jenkins.memorymap.util.HexUtils;
import net.praqma.jenkins.memorymap.util.HexUtils.HexifiableString;
import net.praqma.jenkins.memorymap.util.MemoryMapMemorySelectionError;
import net.sf.json.JSONObject;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

/**
* @author Praqma
*/
public class PowerPCEabiGccMemoryMapParser extends AbstractMemoryMapParser implements Serializable {

private static final Pattern MEM_SECTIONS = Pattern.compile("^\\s*(\\S+)(?=.*:)", Pattern.MULTILINE);
private static final Pattern COMMENT_BLOCKS = Pattern.compile("\\/\\*[\\s\\S]*?\\*\\/");
private static final Logger LOG = Logger.getLogger(PowerPCEabiGccMemoryMapParser.class.getName());

@DataBoundConstructor
public PowerPCEabiGccMemoryMapParser(String parserUniqueName, String mapFile, String configurationFile, Integer wordSize, Boolean bytesOnGraph, List<MemoryMapGraphConfiguration> graphConfiguration) {
super(parserUniqueName, mapFile, configurationFile, wordSize, bytesOnGraph, graphConfiguration);
}

/**
* Strip any c-style block comments, e.g slash-star to star-slash.
* <b>Note:</b> this function down not correctly handle nested comment
* blocks.
* <b>Note:</b> this function is a bit greedy, and will incorrectly strip
* comments inside strings, but this shouldn't be a problem for memory
* config files.
*
* @param seq The content of a file that might contain c-style
* block-comments
* @return The same content, that has now had all block-comments stripped
* out.
*/
public static CharSequence stripComments(CharSequence seq) {
Matcher commentMatcher = COMMENT_BLOCKS.matcher(seq);
return commentMatcher.replaceAll("");
}

/**
* Parses the MEMORY section of the GCC file. Throws an abort exception
* which will be shown in the Jenkins console log.
*
* @param seq The content of the map file
* @return a list of the defined MEMORY in the map file
* @throws hudson.AbortException when a illegal value of memory found
*
*/
public MemoryMapConfigMemory getMemory(CharSequence seq) throws AbortException {

Pattern allMemory = Pattern.compile("^\\s*(\\S+).*?(?:ORIGIN|org|o)\\s*=\\s*\\(([^,]*)\\).*?(?:LENGTH|len|l)\\s*\\=\\s*([^\\s]*.*)", Pattern.MULTILINE);
Matcher match = allMemory.matcher(seq);
MemoryMapConfigMemory memory = new MemoryMapConfigMemory();
while (match.find()) {
String sectionName = match.group(1);
String sectionAddress = match.group(2).replace("(", "").replace(")", "").replace(" ", "");
String sectionLength = match.group(3).replace("(", "").replace(")", "").replace(" ", "");

sectionAddress = getHexSum(sectionAddress);
sectionLength = getHexSum(sectionLength);

try {
String hexLength = new HexUtils.HexifiableString(sectionLength).toValidHexString().rawString;
MemoryMapConfigMemoryItem item = new MemoryMapConfigMemoryItem(sectionName, sectionAddress, hexLength);
memory.add(item);
} catch (Throwable ex) {
logger.log(Level.SEVERE, "Unable to convert %s to a valid hex string.", ex);
throw new AbortException(String.format("Unable to convert %s to a valid hex string.", sectionLength));
}
}
return memory;
}

private static String getHexSum(String group)
{
Long sum = Long.valueOf(0L);

String buff = group.replace("0x", "");
try
{
String[] groupPluses = buff.split("\\+");
if (groupPluses.length > 0) {
for (String str1 : groupPluses)
{
String[] minusGroup = str1.split("\\-");
if (minusGroup.length > 0) {
for (int i = 0; i < minusGroup.length; i++) {
if (i == 0) {
sum = Long.valueOf(sum.longValue() + Long.parseLong(minusGroup[i], 16));
} else {
sum = Long.valueOf(sum.longValue() - Long.parseLong(minusGroup[i], 16));
}
}
} else {
sum = Long.valueOf(sum.longValue() + Long.parseLong(str1, 16));
}
}
} else {
sum = Long.valueOf(sum.longValue() + Long.parseLong(group, 16));
}
}
catch (NumberFormatException ex)
{
return group;
}
return "0x" + Long.toHexString(sum.longValue());
}

/*
* SECTIONS {
* ---
* secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents } >region =fill
...
}
*
*/
public List<MemoryMapConfigMemoryItem> getSections(CharSequence m) {
List<MemoryMapConfigMemoryItem> items = new ArrayList<>();

Pattern section = Pattern.compile("SECTIONS\\s?\\r?\\n?\\{([\\s\\S]*)\\n\\}", Pattern.MULTILINE);

Matcher sectionMatched = section.matcher(m);
String sectionString = null;

while (sectionMatched.find()) {
sectionString = sectionMatched.group(1);
}

//Find the good stuff (SECTION): *SECTIONS\n\{(.*)\n\}
Matcher fm = MEM_SECTIONS.matcher(sectionString);

while (fm.find()) {
MemoryMapConfigMemoryItem it = new MemoryMapConfigMemoryItem(fm.group(1), "0");
items.add(it);
}
return items;
}

public PowerPCEabiGccMemoryMapParser() {
super();
}

public Pattern getLinePatternForMapFile(String sectionName) {
return Pattern.compile(String.format("^(%s)(\\s+)(\\w+)(\\s+)(\\w+)(\\w*)", sectionName), Pattern.MULTILINE);
}

private static class MemoryMapMemItemComparator implements Comparator<MemoryMapConfigMemoryItem>, Serializable {
@Override
public int compare(MemoryMapConfigMemoryItem t, MemoryMapConfigMemoryItem t1) {
long vt = new HexifiableString(t.getOrigin()).getLongValue();
long vt1 = new HexifiableString(t1.getOrigin()).getLongValue();
return (vt < vt1 ? -1 : (vt == vt1 ? 1 : 0));
}
}

/**
* Given an item with length == null. Look down in the list. If we find an
* item whose length is not null, set the items length to that
*
* @param memory the memory list
* @return a more complete configuration, where i have better values
*/
public MemoryMapConfigMemory guessLengthOfSections(MemoryMapConfigMemory memory) {
Collections.sort(memory, new MemoryMapMemItemComparator());

for (MemoryMapConfigMemoryItem item : memory) {
if (item.getLength() == null) {
int itemIndex = memory.indexOf(item);
for (int i = itemIndex; i > 1; i--) {
if (memory.get(i).getLength() != null) {
item.setParent(memory.get(i));
break;
}
}

}
}
return memory;
}

@Override
public MemoryMapConfigMemory parseMapFile(File f, MemoryMapConfigMemory configuration) throws IOException {
CharSequence sequence = createCharSequenceFromFile(f);

for (MemoryMapConfigMemoryItem item : configuration) {
Matcher m = getLinePatternForMapFile(item.getName()).matcher(sequence);
while (m.find()) {
item.setOrigin(m.group(3));
item.setUsed(m.group(5));
}
}

configuration = guessLengthOfSections(configuration);

return configuration;
}

@Override
public MemoryMapConfigMemory parseConfigFile(File f) throws IOException {
//Collect sections from both the MEMORY and the SECTIONS areas from the command file.
//The memory are the top level components, sections belong to one of these sections
CharSequence stripped = stripComments(createCharSequenceFromFile(f));

MemoryMapConfigMemory memConfig = getMemory(stripped);
memConfig.addAll(getSections(stripped));
for (MemoryMapGraphConfiguration g : getGraphConfiguration()) {
for (String gItem : g.itemizeGraphDataList()) {
for (String gSplitItem : gItem.split("\\+")) {
//We will fail if the name of the data section does not match any of the named items in the map file.
if (!memConfig.containsSectionWithName(gSplitItem)) {
throw new MemoryMapMemorySelectionError(String.format("The memory section named %s not found in map file%nAvailable sections are:%n%s", gSplitItem, memConfig.getItemNames()));
}
}
}
}
return memConfig;
}

@Override
public int getDefaultWordSize() {
return 8;
}

@Symbol("powerPCEabiGccParser")
@Extension
public static final class DescriptorImpl extends MemoryMapParserDescriptor<PowerPCEabiGccMemoryMapParser> {

@Override
public String getDisplayName() {
return "PowerPCEabiGcc";
}

@Override
public AbstractMemoryMapParser newInstance(StaplerRequest req, JSONObject formData, AbstractMemoryMapParser instance) throws FormException {
PowerPCEabiGccMemoryMapParser parser = (PowerPCEabiGccMemoryMapParser) instance;
save();
return parser;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<st:include class="net.praqma.jenkins.memorymap.parser.AbstractMemoryMapParser" page="config.jelly"/>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* The MIT License
*
* Copyright 2019 Praqma.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package net.praqma.jenkins.integration;

import java.util.Arrays;
import java.util.HashMap;
import java.util.UUID;
import net.praqma.jenkins.memorymap.graph.MemoryMapGraphConfiguration;
import net.praqma.jenkins.memorymap.parser.powerpceabigcc.PowerPCEabiGccMemoryMapParser;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;

/**
*
* @author thi
*/
public class PowerPCEabiGccMemoryMapParserIT {

@Rule
public JenkinsRule jenkins = new JenkinsRule();

@Test
public void powerpceabigcc_testUsageValues() throws Exception {
MemoryMapGraphConfiguration graphConfiguration = new MemoryMapGraphConfiguration(".text+.rodata", "432");
PowerPCEabiGccMemoryMapParser parser = createParser(graphConfiguration);
parser.setMapFile("prom.map");
parser.setConfigurationFile("prom.ld");

HashMap<String, String> expectedValues = new HashMap<>();
expectedValues.put(".text", "0x10a008");
expectedValues.put(".rodata", "0x33fd7");

TestUtils.testUsageValues(jenkins, parser, "powerpceabigcc.zip", expectedValues);
}

private PowerPCEabiGccMemoryMapParser createParser(MemoryMapGraphConfiguration... graphConfiguration) {
return new PowerPCEabiGccMemoryMapParser(UUID.randomUUID().toString(), null, null, 8, true, Arrays.asList(graphConfiguration));
}
}
Binary file not shown.