native.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import styled from '@emotion/styled';
  2. import scrollToElement from 'scroll-to-element';
  3. import {t} from 'sentry/locale';
  4. import {DebugMetaActions} from 'sentry/stores/debugMetaStore';
  5. import space from 'sentry/styles/space';
  6. import {Frame} from 'sentry/types';
  7. import DebugImage from '../../debugMeta/debugImage';
  8. import {combineStatus} from '../../debugMeta/utils';
  9. import {SymbolicatorStatus} from '../../types';
  10. import PackageLink from '../packageLink';
  11. import PackageStatus from '../packageStatus';
  12. import Symbol from '../symbol';
  13. import TogglableAddress from '../togglableAddress';
  14. import {getPlatform} from '../utils';
  15. import Expander from './expander';
  16. import LeadHint from './leadHint';
  17. import Wrapper from './wrapper';
  18. type Props = React.ComponentProps<typeof Expander> &
  19. React.ComponentProps<typeof LeadHint> & {
  20. frame: Frame;
  21. isUsedForGrouping: boolean;
  22. image?: React.ComponentProps<typeof DebugImage>['image'];
  23. includeSystemFrames?: boolean;
  24. isFrameAfterLastNonApp?: boolean;
  25. maxLengthOfRelativeAddress?: number;
  26. onAddressToggle?: (event: React.MouseEvent<SVGElement>) => void;
  27. onClick?: () => void;
  28. onFunctionNameToggle?: (event: React.MouseEvent<SVGElement>) => void;
  29. onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
  30. prevFrame?: Frame;
  31. showCompleteFunctionName?: boolean;
  32. showingAbsoluteAddress?: boolean;
  33. };
  34. function Native({
  35. frame,
  36. isFrameAfterLastNonApp,
  37. isExpanded,
  38. isHoverPreviewed,
  39. onAddressToggle,
  40. image,
  41. includeSystemFrames,
  42. showingAbsoluteAddress,
  43. showCompleteFunctionName,
  44. onFunctionNameToggle,
  45. maxLengthOfRelativeAddress,
  46. platform,
  47. prevFrame,
  48. isUsedForGrouping,
  49. nextFrame,
  50. leadsToApp,
  51. onMouseDown,
  52. onClick,
  53. ...props
  54. }: Props) {
  55. const {instructionAddr, trust, addrMode, symbolicatorStatus} = frame ?? {};
  56. function packageStatus() {
  57. // this is the status of image that belongs to this frame
  58. if (!image) {
  59. return 'empty';
  60. }
  61. const combinedStatus = combineStatus(image.debug_status, image.unwind_status);
  62. switch (combinedStatus) {
  63. case 'unused':
  64. return 'empty';
  65. case 'found':
  66. return 'success';
  67. default:
  68. return 'error';
  69. }
  70. }
  71. function makeFilter(addr: string): string {
  72. if (!(!addrMode || addrMode === 'abs') && image) {
  73. return `${image.debug_id}!${addr}`;
  74. }
  75. return addr;
  76. }
  77. function scrollToImage(event: React.MouseEvent<HTMLAnchorElement>) {
  78. event.stopPropagation(); // to prevent collapsing if collapsible
  79. if (instructionAddr) {
  80. DebugMetaActions.updateFilter(makeFilter(instructionAddr));
  81. }
  82. scrollToElement('#images-loaded');
  83. }
  84. const shouldShowLinkToImage =
  85. !!symbolicatorStatus &&
  86. symbolicatorStatus !== SymbolicatorStatus.UNKNOWN_IMAGE &&
  87. !isHoverPreviewed;
  88. const isInlineFrame =
  89. prevFrame &&
  90. getPlatform(frame.platform, platform ?? 'other') ===
  91. (prevFrame.platform || platform) &&
  92. instructionAddr === prevFrame.instructionAddr;
  93. const isFoundByStackScanning = trust === 'scan' || trust === 'cfi-scan';
  94. return (
  95. <Wrapper className="title as-table" onMouseDown={onMouseDown} onClick={onClick}>
  96. <NativeLineContent isFrameAfterLastNonApp={!!isFrameAfterLastNonApp}>
  97. <PackageInfo>
  98. <LeadHint
  99. isExpanded={isExpanded}
  100. nextFrame={nextFrame}
  101. leadsToApp={leadsToApp}
  102. />
  103. <PackageLink
  104. includeSystemFrames={!!includeSystemFrames}
  105. withLeadHint={!(isExpanded || !leadsToApp)}
  106. packagePath={frame.package}
  107. onClick={scrollToImage}
  108. isClickable={shouldShowLinkToImage}
  109. isHoverPreviewed={isHoverPreviewed}
  110. >
  111. {!isHoverPreviewed && (
  112. <PackageStatus
  113. status={packageStatus()}
  114. tooltip={t('Go to Images Loaded')}
  115. />
  116. )}
  117. </PackageLink>
  118. </PackageInfo>
  119. {instructionAddr && (
  120. <TogglableAddress
  121. address={instructionAddr}
  122. startingAddress={image ? image.image_addr : null}
  123. isAbsolute={!!showingAbsoluteAddress}
  124. isFoundByStackScanning={isFoundByStackScanning}
  125. isInlineFrame={!!isInlineFrame}
  126. onToggle={onAddressToggle}
  127. relativeAddressMaxlength={maxLengthOfRelativeAddress}
  128. isHoverPreviewed={isHoverPreviewed}
  129. />
  130. )}
  131. <Symbol
  132. frame={frame}
  133. showCompleteFunctionName={!!showCompleteFunctionName}
  134. onFunctionNameToggle={onFunctionNameToggle}
  135. isHoverPreviewed={isHoverPreviewed}
  136. isUsedForGrouping={isUsedForGrouping}
  137. />
  138. </NativeLineContent>
  139. <Expander
  140. isExpanded={isExpanded}
  141. isHoverPreviewed={isHoverPreviewed}
  142. platform={platform}
  143. {...props}
  144. />
  145. </Wrapper>
  146. );
  147. }
  148. export default Native;
  149. const PackageInfo = styled('span')`
  150. display: grid;
  151. grid-template-columns: auto 1fr;
  152. order: 2;
  153. align-items: flex-start;
  154. @media (min-width: ${props => props.theme.breakpoints.small}) {
  155. order: 0;
  156. }
  157. `;
  158. const NativeLineContent = styled('div')<{isFrameAfterLastNonApp: boolean}>`
  159. display: grid;
  160. flex: 1;
  161. gap: ${space(0.5)};
  162. grid-template-columns: auto 1fr;
  163. align-items: center;
  164. justify-content: flex-start;
  165. @media (min-width: ${props => props.theme.breakpoints.small}) {
  166. grid-template-columns:
  167. ${p => (p.isFrameAfterLastNonApp ? '200px' : '150px')} minmax(117px, auto)
  168. 1fr;
  169. }
  170. @media (min-width: ${props => props.theme.breakpoints.large}) and (max-width: ${props =>
  171. props.theme.breakpoints.xlarge}) {
  172. grid-template-columns:
  173. ${p => (p.isFrameAfterLastNonApp ? '180px' : '140px')} minmax(117px, auto)
  174. 1fr;
  175. }
  176. `;