/// <summary> /// A function to extract the debug_info and store it for future reference /// </summary> /// <param name="nmPath"></param> /// <param name="elfPath"></param> public void Run(string readElfPath, string elfPath) { string result = ""; if (elfPath == "" || readElfPath == "") { return; } ProcessAdapter.Execute(ref result, readElfPath, "--debug-dump=info " + Quote(elfPath)); string[] lines = result.Split(new[] { '\r', '\n' }); DwarfInfo = lines.ToList(); CompilationUnits = new List <string[]>(); // Select the index of all lines that contain the compilation unit tag var ci = DwarfInfo.Select((s, i) => new { s, i }).Where(x => x.s.Contains(COMPILE_UNIT)).Select(x => x.i).ToList(); ci.Add(DwarfInfo.Count - 1); // last index for (int i = 0; i < ci.Count - 1; i++) { CompilationUnits.Add(DwarfInfo.GetRange(ci[i], ci[i + 1] - ci[i]).ToArray()); } // test //FindSymbolCUnit("gRecipeFwd", Convert.ToUInt32("1074", 16)); //FindSubRoutineCUnit("vSPIM_Task", Convert.ToUInt32("4ecc", 16)); //FindSubRoutineCUnit("gRecipeFwd", Convert.ToUInt32("1075", 16)); }
/// <summary> /// Input the search path for .o files. We extract all the resolved symbols inside each .o file and store them for future reference /// </summary> /// <param name="nmPath"></param> /// <param name="objSearchPaths"></param> public void GatherStaticSyms(string nmPath, string[] objSearchPaths) { string result = ""; UnresolvedSymols = new List <Symbol>(); // 1. Extract all the object files from the various directories // Note select() doesnt execute the where() filter, but selectmany works! var objs = objSearchPaths.SelectMany(x => Directory.GetFiles(x).Where(y => { if ((Path.GetExtension(y).ToLower() == ".o" || Path.GetExtension(y).ToLower() == ".obj")) { return(true); } else { return(false); } })); // 2. Run NM on them and get their symbols foreach (var obj in objs) { ProcessAdapter.Execute(ref result, nmPath, "--print-size --size-sort " + Quote(obj.ToString())); string[] symTable = result.Split(new[] { '\r', '\n' }); string secName = "unknown"; foreach (string line in symTable) { string[] entries = line.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); if (entries.Length < 3) { continue; } // We are only interested in local symbols -> lower case stuff except for C // https://sourceware.org/binutils/docs/binutils/nm.html if (entries[2] == "t") { secName = SEC_NAME_TEXT; } else if (Regex.IsMatch(entries[2], @"[dg]")) { secName = SEC_NAME_DATA; } else if (Regex.IsMatch(entries[2], @"[bCs]")) { secName = SEC_NAME_BSS; } else { continue; } Symbol sym = new Symbol(entries[3], obj.ToString(), Convert.ToUInt32(entries[0], 16), Convert.ToUInt32(entries[1], 16), secName); sym.GlobalScope = Symbol.TYPE_STATIC; UnresolvedSymols.Add(sym); } } }
public void Run(string nmPath, string elfPath) { string result = ""; Symbols = new List <Symbol>(); if (elfPath == "") { return; } ProcessAdapter.Execute(ref result, nmPath, "--demangle --print-size --size-sort " + Quote(elfPath)); //--line-numbers // Parse the resultant table // 00800744 00000004 b LoaderIPMode --> b means static BSS symbol, B beans global BSS symbol, same for d/D data // 00006364 00000018 T vTaskSuspendAll /cygdrive/d/Freelance/Study/FTDI/VFWLoaderDemo/lib/FreeRTOS/Source/tasks.c:1632 string[] symTable = result.Split(new[] { '\r', '\n' }); foreach (string line in symTable) { // Split using spaces - note that the module path may itself contain spaces string[] entries = line.Split(new char[0], 4, StringSplitOptions.RemoveEmptyEntries); if (entries.Length < 4) { continue; } string path = ""; int type = Symbol.TYPE_STATIC; string secName = "unknown"; // Extract the module path, we also take into account paths with spaces in between if (entries[3] == "_setlocale_r") { Debug.Write("_setlocale_r"); } entries[3] = entries[3].TrimEnd(' '); // trim spaces from the end of function name if (UseDWARF) { // Extract module path from DARF info if (entries[2].ToLower() == "t") { // Subroutines path = DwarfParser.Instance.FindSubRoutineCUnit(entries[3], Convert.ToUInt32(entries[0], 16)); } else if (entries[2].ToLower() == "w") // Weak symbols could be either vars or subroutines { Debug.WriteLine("Found a weak symbol " + entries[3]); path = DwarfParser.Instance.FindSubRoutineCUnit(entries[3], Convert.ToUInt32(entries[0], 16)); if (path != String.Empty) { Debug.WriteLine("Is a subroutine " + path); } else { path = DwarfParser.Instance.FindSymbolCUnit(entries[3], Convert.ToUInt32(entries[0], 16) & (~RAM_ADDRESS_MASK)); if (path != String.Empty) { Debug.WriteLine("Is a variable " + path); // FIXME: for now just assume all weak variable syms are in BSS entries[2] = "b"; } } } else { // variables path = DwarfParser.Instance.FindSymbolCUnit(entries[3], Convert.ToUInt32(entries[0], 16) & (~RAM_ADDRESS_MASK)); } } else { if (entries.Length > 4) { int end = line.IndexOf(':'); int j = 0; for (int i = 0; i < line.Length; i++) { // Find the index of 4th space if (line[i] == ' ' || line[i] == '\t') { j++; if (j == 4) { j = i + 1; break; } } } path = line.Substring(j, end - j); } } if (Regex.IsMatch(entries[2], @"[TDBGSR]")) { type = Symbol.TYPE_GLOBAL; } // Get the section if (entries[2].ToLower() == "t") { secName = SEC_NAME_TEXT; } if (entries[2].ToLower() == "d" || entries[2].ToLower() == "g" || entries[2].ToLower() == "r") { secName = SEC_NAME_DATA; } if (entries[2].ToLower() == "b" || entries[2].ToLower() == "s" || entries[2].ToLower() == "c") { secName = SEC_NAME_BSS; } Symbol sym = new Symbol(entries[3], path, Convert.ToUInt32(entries[0], 16), Convert.ToUInt32(entries[1], 16), secName); sym.GlobalScope = type; Symbols.Add(sym); } }