diff --git a/package.json b/package.json index 11cdfef..ad4db31 100644 --- a/package.json +++ b/package.json @@ -200,6 +200,19 @@ "default": 4, "description": "Default groups per row" }, + "memory-inspector.endianness": { + "type": "string", + "enum": [ + "Big Endian", + "Little Endian" + ], + "enumDescriptions": [ + "Most significant byte stored at smallest memory address", + "Least significant byte stored at smallest memory address" + ], + "default": "Little Endian", + "description": "Order of bytes within a group" + }, "memory-inspector.columns.variables": { "type": "boolean", "default": false, diff --git a/src/common/memory-range.ts b/src/common/memory-range.ts index a76df7d..8205ede 100644 --- a/src/common/memory-range.ts +++ b/src/common/memory-range.ts @@ -119,3 +119,8 @@ export function areVariablesEqual(one: BigIntVariableRange, other: BigIntVariabl export function toOffset(startAddress: bigint, targetAddress: bigint, wordSize: number): number { return Number(targetAddress - startAddress) * (wordSize / 8); } + +export enum Endianness { + Little = 'Little Endian', + Big = 'Big Endian' +} diff --git a/src/plugin/manifest.ts b/src/plugin/manifest.ts index 62b5d7c..e27a330 100644 --- a/src/plugin/manifest.ts +++ b/src/plugin/manifest.ts @@ -14,6 +14,8 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ +import { Endianness } from '../common/memory-range'; + // Common export const PACKAGE_NAME = 'memory-inspector'; export const DISPLAY_NAME = 'Memory Inspector'; @@ -45,6 +47,10 @@ export const CONFIG_GROUPS_PER_ROW_CHOICES = ['Autofit', ...CONFIG_GROUPS_PER_RO export type GroupsPerRowOption = (typeof CONFIG_GROUPS_PER_ROW_CHOICES)[number]; export const DEFAULT_GROUPS_PER_ROW: GroupsPerRowOption = 4; +// - Group Endianness +export const CONFIG_ENDIANNESS = 'endianness'; +export const DEFAULT_ENDIANNESS = Endianness.Little; + // Scroll export const CONFIG_SCROLLING_BEHAVIOR = 'scrollingBehavior'; export const DEFAULT_SCROLLING_BEHAVIOR = 'Paginate'; diff --git a/src/plugin/memory-webview-main.ts b/src/plugin/memory-webview-main.ts index 89ac77c..84deda6 100644 --- a/src/plugin/memory-webview-main.ts +++ b/src/plugin/memory-webview-main.ts @@ -34,7 +34,7 @@ import { } from '../common/messaging'; import { MemoryProvider } from './memory-provider'; import { outputChannelLogger } from './logger'; -import { VariableRange } from '../common/memory-range'; +import { Endianness, VariableRange } from '../common/memory-range'; import { AddressPaddingOptions, MemoryViewSettings, ScrollingBehavior } from '../webview/utils/view-types'; interface Variable { @@ -221,6 +221,7 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider { const bytesPerWord = memoryInspectorConfiguration.get(manifest.CONFIG_BYTES_PER_WORD, manifest.DEFAULT_BYTES_PER_WORD); const wordsPerGroup = memoryInspectorConfiguration.get(manifest.CONFIG_WORDS_PER_GROUP, manifest.DEFAULT_WORDS_PER_GROUP); const groupsPerRow = memoryInspectorConfiguration.get(manifest.CONFIG_GROUPS_PER_ROW, manifest.DEFAULT_GROUPS_PER_ROW); + const endianness = memoryInspectorConfiguration.get(manifest.CONFIG_ENDIANNESS, manifest.DEFAULT_ENDIANNESS); const scrollingBehavior = memoryInspectorConfiguration.get(manifest.CONFIG_SCROLLING_BEHAVIOR, manifest.DEFAULT_SCROLLING_BEHAVIOR); const visibleColumns = CONFIGURABLE_COLUMNS .filter(column => vscode.workspace.getConfiguration(manifest.PACKAGE_NAME).get(column, false)) @@ -228,7 +229,7 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider { const addressPadding = AddressPaddingOptions[memoryInspectorConfiguration.get(manifest.CONFIG_ADDRESS_PADDING, manifest.DEFAULT_ADDRESS_PADDING)]; const addressRadix = memoryInspectorConfiguration.get(manifest.CONFIG_ADDRESS_RADIX, manifest.DEFAULT_ADDRESS_RADIX); const showRadixPrefix = memoryInspectorConfiguration.get(manifest.CONFIG_SHOW_RADIX_PREFIX, manifest.DEFAULT_SHOW_RADIX_PREFIX); - return { title, bytesPerWord, wordsPerGroup, groupsPerRow, scrollingBehavior, visibleColumns, addressPadding, addressRadix, showRadixPrefix }; + return { title, bytesPerWord, wordsPerGroup, groupsPerRow, endianness, scrollingBehavior, visibleColumns, addressPadding, addressRadix, showRadixPrefix }; } protected async readMemory(request: DebugProtocol.ReadMemoryArguments): Promise { diff --git a/src/webview/columns/data-column.tsx b/src/webview/columns/data-column.tsx index 2cc44bc..8b41cd9 100644 --- a/src/webview/columns/data-column.tsx +++ b/src/webview/columns/data-column.tsx @@ -15,7 +15,7 @@ ********************************************************************************/ import * as React from 'react'; -import { BigIntMemoryRange, toOffset } from '../../common/memory-range'; +import { BigIntMemoryRange, Endianness, toOffset } from '../../common/memory-range'; import { FullNodeAttributes, Memory } from '../utils/view-types'; import { ColumnContribution, TableRenderOptions } from './column-contribution-service'; import { decorationService } from '../decorations/decoration-service'; @@ -40,14 +40,14 @@ export class DataColumn implements ColumnContribution { protected renderGroups(range: BigIntMemoryRange, memory: Memory, options: TableRenderOptions): React.ReactNode { const groups = []; - let words = []; - for (let i = range.startAddress; i < range.endAddress; i++) { - words.push(this.renderWord(memory, options, i)); + let words: React.ReactNode[] = []; + for (let address = range.startAddress; address < range.endAddress; address++) { + words.push(this.renderWord(memory, options, address)); if (words.length % options.wordsPerGroup === 0) { - const isLast = i + 1n >= range.endAddress; + this.applyEndianness(words, options); + const isLast = address + 1n >= range.endAddress; const style: React.CSSProperties | undefined = isLast ? undefined : this.byteGroupStyle; - - groups.push({words}); + groups.push({words}); words = []; } } @@ -58,13 +58,19 @@ export class DataColumn implements ColumnContribution { protected renderWord(memory: Memory, options: TableRenderOptions, currentAddress: bigint): React.ReactNode { const initialOffset = toOffset(memory.address, currentAddress, options.bytesPerWord * 8); const finalOffset = initialOffset + options.bytesPerWord; - const bytes = []; + const bytes: React.ReactNode[] = []; for (let i = initialOffset; i < finalOffset; i++) { bytes.push(this.renderEightBits(memory, currentAddress, i)); } + this.applyEndianness(bytes, options); return {bytes}; } + protected applyEndianness(group: T[], options: TableRenderOptions): T[] { + // Assume data from the DAP comes in Big Endian so we need to revert the order if we use Little Endian + return options.endianness === Endianness.Big ? group : group.reverse(); + } + protected renderEightBits(memory: Memory, currentAddress: bigint, offset: number): React.ReactNode { const { content, className, style, title } = this.getBitAttributes(memory, currentAddress, offset); return { @@ -62,7 +60,7 @@ export class MemoryWidget extends React.Component candidate.active)} memory={this.props.memory} - endianness={this.state.endianness} + endianness={this.props.endianness} bytesPerWord={this.props.bytesPerWord} wordsPerGroup={this.props.wordsPerGroup} groupsPerRow={this.props.groupsPerRow} diff --git a/src/webview/components/options-widget.tsx b/src/webview/components/options-widget.tsx index 6a7eb82..c7bac50 100644 --- a/src/webview/components/options-widget.tsx +++ b/src/webview/components/options-widget.tsx @@ -28,6 +28,7 @@ import { MultiSelectWithLabel } from './multi-select'; import { CONFIG_BYTES_PER_WORD_CHOICES, CONFIG_GROUPS_PER_ROW_CHOICES, CONFIG_WORDS_PER_GROUP_CHOICES } from '../../plugin/manifest'; import { tryToNumber } from '../../common/typescript'; import { Checkbox } from 'primereact/checkbox'; +import { Endianness } from '../../common/memory-range'; export interface OptionsWidgetProps extends Omit { @@ -55,6 +56,7 @@ const enum InputId { BytesPerWord = 'word-size', WordsPerGroup = 'words-per-group', GroupsPerRow = 'groups-per-row', + EndiannessId = 'endianness', AddressPadding = 'address-padding', AddressRadix = 'address-radix', ShowRadixPrefix = 'show-radix-prefix', @@ -326,6 +328,19 @@ export class OptionsWidget extends React.Component + + +

Address Format