зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
50a315138b
|
@ -1502,11 +1502,6 @@ pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla.
|
|||
// Enable GMP support in the addon manager.
|
||||
pref("media.gmp-provider.enabled", true);
|
||||
|
||||
// Enable blocking access to storage from tracking resources by default on Nightly
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("network.cookie.cookieBehavior", 4 /* BEHAVIOR_REJECT_TRACKER */);
|
||||
#endif
|
||||
|
||||
pref("browser.contentblocking.allowlist.storage.enabled", true);
|
||||
|
||||
pref("browser.contentblocking.global-toggle.enabled", true);
|
||||
|
|
|
@ -391,17 +391,18 @@ ContentPrincipal::SetDomain(nsIURI* aDomain)
|
|||
}
|
||||
|
||||
static nsresult
|
||||
GetBaseDomainHelper(const nsCOMPtr<nsIURI>& aCodebase,
|
||||
bool* aHasBaseDomain,
|
||||
nsACString& aBaseDomain)
|
||||
GetSpecialBaseDomain(const nsCOMPtr<nsIURI>& aCodebase,
|
||||
bool* aHandled,
|
||||
nsACString& aBaseDomain)
|
||||
{
|
||||
*aHasBaseDomain = false;
|
||||
*aHandled = false;
|
||||
|
||||
// For a file URI, we return the file path.
|
||||
if (NS_URIIsLocalFile(aCodebase)) {
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(aCodebase);
|
||||
|
||||
if (url) {
|
||||
*aHandled = true;
|
||||
return url->GetFilePath(aBaseDomain);
|
||||
}
|
||||
}
|
||||
|
@ -415,52 +416,84 @@ GetBaseDomainHelper(const nsCOMPtr<nsIURI>& aCodebase,
|
|||
}
|
||||
|
||||
if (hasNoRelativeFlag) {
|
||||
*aHandled = true;
|
||||
return aCodebase->GetSpec(aBaseDomain);
|
||||
}
|
||||
|
||||
*aHasBaseDomain = true;
|
||||
|
||||
// For everything else, we ask the TLD service via
|
||||
// the ThirdPartyUtil.
|
||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
|
||||
do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
||||
if (thirdPartyUtil) {
|
||||
return thirdPartyUtil->GetBaseDomain(aCodebase, aBaseDomain);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentPrincipal::GetBaseDomain(nsACString& aBaseDomain)
|
||||
{
|
||||
bool hasBaseDomain;
|
||||
return GetBaseDomainHelper(mCodebase, &hasBaseDomain, aBaseDomain);
|
||||
// Handle some special URIs first.
|
||||
bool handled;
|
||||
nsresult rv = GetSpecialBaseDomain(mCodebase, &handled, aBaseDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (handled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// For everything else, we ask the TLD service via the ThirdPartyUtil.
|
||||
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
|
||||
do_GetService(THIRDPARTYUTIL_CONTRACTID);
|
||||
if (!thirdPartyUtil) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ContentPrincipal::GetSiteOrigin(nsACString& aSiteOrigin)
|
||||
{
|
||||
// Determine our base domain.
|
||||
bool hasBaseDomain;
|
||||
// Handle some special URIs first.
|
||||
nsAutoCString baseDomain;
|
||||
nsresult rv = GetBaseDomainHelper(mCodebase, &hasBaseDomain, baseDomain);
|
||||
bool handled;
|
||||
nsresult rv = GetSpecialBaseDomain(mCodebase, &handled, baseDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!hasBaseDomain) {
|
||||
if (handled) {
|
||||
// This is a special URI ("file:", "about:", "view-source:", etc). Just
|
||||
// return the origin.
|
||||
return GetOrigin(aSiteOrigin);
|
||||
}
|
||||
|
||||
// For everything else, we ask the TLD service. Note that, unlike in
|
||||
// GetBaseDomain, we don't use ThirdPartyUtil.getBaseDomain because if the
|
||||
// host is an IP address that returns the raw address and we can't use it with
|
||||
// SetHost below because SetHost expects '[' and ']' around IPv6 addresses.
|
||||
// See bug 1491728.
|
||||
nsCOMPtr<nsIEffectiveTLDService> tldService =
|
||||
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
|
||||
if (!tldService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool gotBaseDomain = false;
|
||||
rv = tldService->GetBaseDomain(mCodebase, 0, baseDomain);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
gotBaseDomain = true;
|
||||
} else {
|
||||
// If this is an IP address or something like "localhost", we just continue
|
||||
// with gotBaseDomain = false.
|
||||
if (rv != NS_ERROR_HOST_IS_IP_ADDRESS &&
|
||||
rv != NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Calling `SetHostPort` with a portless domain is insufficient to clear
|
||||
// the port, so an extra `SetPort` call has to be made.
|
||||
nsCOMPtr<nsIURI> siteUri;
|
||||
rv = NS_MutateURI(mCodebase)
|
||||
.SetUserPass(EmptyCString())
|
||||
.SetPort(-1)
|
||||
.SetHostPort(baseDomain)
|
||||
.Finalize(siteUri);
|
||||
NS_MutateURI mutator(mCodebase);
|
||||
mutator.SetUserPass(EmptyCString())
|
||||
.SetPort(-1);
|
||||
if (gotBaseDomain) {
|
||||
mutator.SetHost(baseDomain);
|
||||
}
|
||||
rv = mutator.Finalize(siteUri);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to create siteUri");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -374,6 +374,11 @@ Animation::UpdatePlaybackRate(double aPlaybackRate)
|
|||
return;
|
||||
}
|
||||
|
||||
// Calculate the play state using the existing playback rate since below we
|
||||
// want to know if the animation is _currently_ finished or not, not whether
|
||||
// it _will_ be finished.
|
||||
AnimationPlayState playState = PlayState();
|
||||
|
||||
mPendingPlaybackRate = Some(aPlaybackRate);
|
||||
|
||||
// If we already have a pending task, there is nothing more to do since the
|
||||
|
@ -384,7 +389,6 @@ Animation::UpdatePlaybackRate(double aPlaybackRate)
|
|||
|
||||
AutoMutationBatchForAnimation mb(*this);
|
||||
|
||||
AnimationPlayState playState = PlayState();
|
||||
if (playState == AnimationPlayState::Idle ||
|
||||
playState == AnimationPlayState::Paused) {
|
||||
// We are either idle or paused. In either case we can apply the pending
|
||||
|
@ -457,9 +461,10 @@ Animation::PlayState() const
|
|||
return AnimationPlayState::Paused;
|
||||
}
|
||||
|
||||
double playbackRate = CurrentOrPendingPlaybackRate();
|
||||
if (!currentTime.IsNull() &&
|
||||
((mPlaybackRate > 0.0 && currentTime.Value() >= EffectEnd()) ||
|
||||
(mPlaybackRate < 0.0 && currentTime.Value() <= TimeDuration()))) {
|
||||
((playbackRate > 0.0 && currentTime.Value() >= EffectEnd()) ||
|
||||
(playbackRate < 0.0 && currentTime.Value() <= TimeDuration()))) {
|
||||
return AnimationPlayState::Finished;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
virtual SyncHandle GetSyncHandle() = 0;
|
||||
|
||||
// Return false for failed synchronization.
|
||||
virtual bool Synchronize(bool aFallible = false) = 0;
|
||||
virtual bool Synchronize() = 0;
|
||||
|
||||
protected:
|
||||
SyncObjectHost() { }
|
||||
|
|
|
@ -1716,24 +1716,22 @@ SyncObjectD3D11Host::GetSyncHandle()
|
|||
}
|
||||
|
||||
bool
|
||||
SyncObjectD3D11Host::Synchronize(bool aFallible)
|
||||
SyncObjectD3D11Host::Synchronize()
|
||||
{
|
||||
HRESULT hr;
|
||||
AutoTextureLock lock(mKeyedMutex, hr, 10000);
|
||||
|
||||
if (hr == WAIT_TIMEOUT) {
|
||||
hr = mDevice->GetDeviceRemovedReason();
|
||||
if (hr != S_OK ) {
|
||||
// Since the timeout is related to the driver-removed. Return false for
|
||||
// error handling.
|
||||
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
|
||||
} else if (aFallible) {
|
||||
gfxCriticalNote << "GFX: D3D11 timeout on the D3D11 sync lock.";
|
||||
} else {
|
||||
if (hr == S_OK) {
|
||||
// There is no driver-removed event. Crash with this timeout.
|
||||
MOZ_CRASH("GFX: D3D11 normal status timeout");
|
||||
}
|
||||
|
||||
// Since the timeout is related to the driver-removed. Return false for
|
||||
// error handling.
|
||||
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (hr == WAIT_ABANDONED) {
|
||||
|
|
|
@ -498,7 +498,7 @@ public:
|
|||
|
||||
virtual SyncHandle GetSyncHandle() override;
|
||||
|
||||
virtual bool Synchronize(bool aFallible) override;
|
||||
virtual bool Synchronize() override;
|
||||
|
||||
IDXGIKeyedMutex* GetKeyedMutex() { return mKeyedMutex.get(); };
|
||||
|
||||
|
|
|
@ -1564,7 +1564,7 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
|
|||
MOZ_ASSERT(aTarget == nullptr);
|
||||
MOZ_ASSERT(aRect == nullptr);
|
||||
|
||||
AUTO_PROFILER_TRACING("Paint", "CompositeToTraget");
|
||||
AUTO_PROFILER_TRACING("Paint", "CompositeToTarget");
|
||||
if (mPaused || !mReceivedDisplayList) {
|
||||
mPreviousFrameTimeStamp = TimeStamp();
|
||||
return;
|
||||
|
|
|
@ -330,7 +330,7 @@ RenderCompositorANGLE::BeginFrame()
|
|||
}
|
||||
|
||||
if (mSyncObject) {
|
||||
if (!mSyncObject->Synchronize(/* aFallible */ true)) {
|
||||
if (!mSyncObject->Synchronize()) {
|
||||
// It's timeout or other error. Handle the device-reset here.
|
||||
RenderThread::Get()->HandleDeviceReset("SyncObject", /* aNotify */ true);
|
||||
return false;
|
||||
|
|
|
@ -22,8 +22,7 @@ test(t => {
|
|||
+ ' and no pending tasks')
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
const animation = createDiv(t).animate({}, 100 * MS_PER_SEC);
|
||||
|
||||
animation.pause();
|
||||
|
||||
|
@ -134,8 +133,7 @@ test(t => {
|
|||
+ ' current time = 0');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate({}, 0);
|
||||
const animation = createDiv(t).animate({}, 0);
|
||||
assert_equals(animation.startTime, null,
|
||||
'Sanity check: start time should be unresolved');
|
||||
|
||||
|
@ -144,8 +142,7 @@ test(t => {
|
|||
+ ' current time = target effect end and there is a pending play task');
|
||||
|
||||
test(t => {
|
||||
const div = createDiv(t);
|
||||
const animation = div.animate({}, 100 * MS_PER_SEC);
|
||||
const animation = createDiv(t).animate({}, 100 * MS_PER_SEC);
|
||||
assert_equals(animation.startTime, null,
|
||||
'Sanity check: start time should be unresolved');
|
||||
|
||||
|
@ -153,5 +150,36 @@ test(t => {
|
|||
}, 'reports \'running\' when playback rate > 0 and'
|
||||
+ ' current time < target effect end and there is a pending play task');
|
||||
|
||||
test(t => {
|
||||
const animation = createDiv(t).animate({}, 100 * MS_PER_SEC);
|
||||
assert_equals(animation.playState, 'running');
|
||||
assert_true(animation.pending);
|
||||
}, 'reports \'running\' for a play-pending animation');
|
||||
|
||||
test(t => {
|
||||
const animation = createDiv(t).animate({}, 100 * MS_PER_SEC);
|
||||
animation.pause();
|
||||
assert_equals(animation.playState, 'paused');
|
||||
assert_true(animation.pending);
|
||||
}, 'reports \'paused\' for a pause-pending animation');
|
||||
|
||||
test(t => {
|
||||
const animation = createDiv(t).animate({}, 0);
|
||||
assert_equals(animation.playState, 'finished');
|
||||
assert_true(animation.pending);
|
||||
}, 'reports \'finished\' for a finished-pending animation');
|
||||
|
||||
test(t => {
|
||||
const animation = createDiv(t).animate({}, 100 * MS_PER_SEC);
|
||||
// Set up the pending playback rate
|
||||
animation.updatePlaybackRate(-1);
|
||||
// Call play again so that we seek to the end while remaining play-pending
|
||||
animation.play();
|
||||
// For a pending animation, the play state should always report what the
|
||||
// play state _will_ be once we finish pending.
|
||||
assert_equals(animation.playState, 'running');
|
||||
assert_true(animation.pending);
|
||||
}, 'reports the play state based on the pending playback rate');
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -1243,6 +1243,10 @@ function expectedOriginFrecency(urls) {
|
|||
* this element can be `undefined`.
|
||||
*/
|
||||
async function checkDB(expectedOrigins) {
|
||||
// Frencencies for bookmarks are generated asynchronously but not within the
|
||||
// await cycle for bookmarks.insert() etc, so wait for them to happen.
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
let rows = await db.execute(`
|
||||
SELECT prefix, host, frecency
|
||||
|
|
|
@ -1773,11 +1773,20 @@ this.VideoControlsImplPageWidget = class {
|
|||
return new Proxy(element, this.reflowTriggeringCallValidator);
|
||||
},
|
||||
|
||||
// Set the values to intrinsic dimensions before the first update.
|
||||
reflowedDimensions: {
|
||||
// Set the dimensions to intrinsic <video> dimensions before the first
|
||||
// update.
|
||||
// These values are not picked up by <audio> in adjustControlSize()
|
||||
// (except for the fact that they are non-zero),
|
||||
// it takes controlBarMinHeight and the value below instead.
|
||||
videoHeight: 150,
|
||||
videoWidth: 300,
|
||||
videocontrolsWidth: 300,
|
||||
|
||||
// <audio> takes this width to grow/shrink controls.
|
||||
// The initial value has to be smaller than the calculated minRequiredWidth
|
||||
// so that we don't run into bug 1495821 (see comment on adjustControlSize()
|
||||
// below)
|
||||
videocontrolsWidth: 0,
|
||||
},
|
||||
|
||||
updateReflowedDimensions() {
|
||||
|
@ -1786,6 +1795,29 @@ this.VideoControlsImplPageWidget = class {
|
|||
this.reflowedDimensions.videocontrolsWidth = this.videocontrols.clientWidth;
|
||||
},
|
||||
|
||||
/**
|
||||
* adjustControlSize() considers outer dimensions of the <video>/<audio> element
|
||||
* from layout, and accordingly, sets/hides the controls, and adjusts
|
||||
* the width/height of the control bar.
|
||||
*
|
||||
* It's important to remember that for <audio>, layout (specifically,
|
||||
* nsVideoFrame) rely on us to expose the intrinsic dimensions of the
|
||||
* control bar to properly size the <audio> element. We interact with layout
|
||||
* by:
|
||||
*
|
||||
* 1) When the element has a non-zero height, explicitly set the height
|
||||
* of the control bar to a size between controlBarMinHeight and
|
||||
* controlBarMinVisibleHeight in response.
|
||||
* Note: the logic here is flawed and had caused the end height to be
|
||||
* depend on its previous state, see bug 1495817.
|
||||
* 2) When the element has a outer width smaller or equal to minControlBarPaddingWidth,
|
||||
* explicitly set the control bar to minRequiredWidth, so that when the
|
||||
* outer width is unset, the audio element could go back to minRequiredWidth.
|
||||
* Otherwise, set the width of the control bar to be the current outer width.
|
||||
* Note: the logic here is also flawed; when the control bar is set to
|
||||
* the current outer width, it never go back when the width is unset,
|
||||
* see bug 1495821.
|
||||
*/
|
||||
adjustControlSize() {
|
||||
const minControlBarPaddingWidth = 18;
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ bool operator<(const EHEntryHandle &lhs, const EHEntryHandle &rhs) {
|
|||
class EHTable {
|
||||
uint32_t mStartPC;
|
||||
uint32_t mEndPC;
|
||||
uint32_t mLoadOffset;
|
||||
uint32_t mBaseAddress;
|
||||
#ifdef HAVE_UNSORTED_EXIDX
|
||||
// In principle we should be able to binary-search the index section in
|
||||
// place, but the ICS toolchain's linker is noncompliant and produces
|
||||
|
@ -134,7 +134,7 @@ public:
|
|||
const std::string &name() const { return mName; }
|
||||
uint32_t startPC() const { return mStartPC; }
|
||||
uint32_t endPC() const { return mEndPC; }
|
||||
uint32_t loadOffset() const { return mLoadOffset; }
|
||||
uint32_t baseAddress() const { return mBaseAddress; }
|
||||
};
|
||||
|
||||
class EHAddrSpace {
|
||||
|
@ -548,12 +548,12 @@ EHTable::EHTable(const void *aELF, size_t aSize, const std::string &aName)
|
|||
#endif
|
||||
mName(aName)
|
||||
{
|
||||
const uint32_t base = reinterpret_cast<uint32_t>(aELF);
|
||||
const uint32_t fileHeaderAddr = reinterpret_cast<uint32_t>(aELF);
|
||||
|
||||
if (aSize < sizeof(Elf32_Ehdr))
|
||||
return;
|
||||
|
||||
const Elf32_Ehdr &file = *(reinterpret_cast<Elf32_Ehdr *>(base));
|
||||
const Elf32_Ehdr &file = *(reinterpret_cast<Elf32_Ehdr *>(fileHeaderAddr));
|
||||
if (memcmp(&file.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 ||
|
||||
file.e_ident[EI_CLASS] != ELFCLASS32 ||
|
||||
file.e_ident[EI_DATA] != hostEndian ||
|
||||
|
@ -571,7 +571,7 @@ EHTable::EHTable(const void *aELF, size_t aSize, const std::string &aName)
|
|||
const Elf32_Phdr *exidxHdr = 0, *zeroHdr = 0;
|
||||
for (unsigned i = 0; i < file.e_phnum; ++i) {
|
||||
const Elf32_Phdr &phdr =
|
||||
*(reinterpret_cast<Elf32_Phdr *>(base + file.e_phoff
|
||||
*(reinterpret_cast<Elf32_Phdr *>(fileHeaderAddr + file.e_phoff
|
||||
+ i * file.e_phentsize));
|
||||
if (phdr.p_type == PT_ARM_EXIDX) {
|
||||
exidxHdr = &phdr;
|
||||
|
@ -589,15 +589,15 @@ EHTable::EHTable(const void *aELF, size_t aSize, const std::string &aName)
|
|||
return;
|
||||
if (!zeroHdr)
|
||||
return;
|
||||
mLoadOffset = base - zeroHdr->p_vaddr;
|
||||
mStartPC += mLoadOffset;
|
||||
mEndPC += mLoadOffset;
|
||||
mBaseAddress = fileHeaderAddr - zeroHdr->p_vaddr;
|
||||
mStartPC += mBaseAddress;
|
||||
mEndPC += mBaseAddress;
|
||||
|
||||
// Create a sorted index of the index to work around linker bugs.
|
||||
const EHEntry *startTable =
|
||||
reinterpret_cast<const EHEntry *>(mLoadOffset + exidxHdr->p_vaddr);
|
||||
reinterpret_cast<const EHEntry *>(mBaseAddress + exidxHdr->p_vaddr);
|
||||
const EHEntry *endTable =
|
||||
reinterpret_cast<const EHEntry *>(mLoadOffset + exidxHdr->p_vaddr
|
||||
reinterpret_cast<const EHEntry *>(mBaseAddress + exidxHdr->p_vaddr
|
||||
+ exidxHdr->p_memsz);
|
||||
#ifdef HAVE_UNSORTED_EXIDX
|
||||
mEntries.reserve(endTable - startTable);
|
||||
|
@ -630,13 +630,9 @@ void EHAddrSpace::Update() {
|
|||
|
||||
for (size_t i = 0; i < info.GetSize(); ++i) {
|
||||
const SharedLibrary &lib = info.GetEntry(i);
|
||||
if (lib.GetOffset() != 0)
|
||||
// TODO: if it has a name, and we haven't seen a mapping of
|
||||
// offset 0 for that file, try opening it and reading the
|
||||
// headers instead. The only thing I've seen so far that's
|
||||
// linked so as to need that treatment is the dynamic linker
|
||||
// itself.
|
||||
continue;
|
||||
// FIXME: This isn't correct if the start address isn't p_offset 0, because
|
||||
// the start address will not point at the file header. But this is worked
|
||||
// around by magic number checks in the EHTable constructor.
|
||||
EHTable tab(reinterpret_cast<const void *>(lib.GetStart()),
|
||||
lib.GetEnd() - lib.GetStart(), lib.GetNativeDebugPath());
|
||||
if (tab.isValid())
|
||||
|
|
|
@ -43,16 +43,19 @@ int dl_iterate_phdr(
|
|||
|
||||
struct LoadedLibraryInfo
|
||||
{
|
||||
LoadedLibraryInfo(const char* aName, unsigned long aStart, unsigned long aEnd)
|
||||
LoadedLibraryInfo(const char* aName, unsigned long aBaseAddress,
|
||||
unsigned long aFirstMappingStart, unsigned long aLastMappingEnd)
|
||||
: mName(aName)
|
||||
, mStart(aStart)
|
||||
, mEnd(aEnd)
|
||||
, mBaseAddress(aBaseAddress)
|
||||
, mFirstMappingStart(aFirstMappingStart)
|
||||
, mLastMappingEnd(aLastMappingEnd)
|
||||
{
|
||||
}
|
||||
|
||||
nsCString mName;
|
||||
unsigned long mStart;
|
||||
unsigned long mEnd;
|
||||
unsigned long mBaseAddress;
|
||||
unsigned long mFirstMappingStart;
|
||||
unsigned long mLastMappingEnd;
|
||||
};
|
||||
|
||||
#if defined(GP_OS_android)
|
||||
|
@ -134,8 +137,9 @@ dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data)
|
|||
if (dl_info->dlpi_phnum <= 0)
|
||||
return 0;
|
||||
|
||||
unsigned long libStart = -1;
|
||||
unsigned long libEnd = 0;
|
||||
unsigned long baseAddress = dl_info->dlpi_addr;
|
||||
unsigned long firstMappingStart = -1;
|
||||
unsigned long lastMappingEnd = 0;
|
||||
|
||||
for (size_t i = 0; i < dl_info->dlpi_phnum; i++) {
|
||||
if (dl_info->dlpi_phdr[i].p_type != PT_LOAD) {
|
||||
|
@ -143,14 +147,16 @@ dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data)
|
|||
}
|
||||
unsigned long start = dl_info->dlpi_addr + dl_info->dlpi_phdr[i].p_vaddr;
|
||||
unsigned long end = start + dl_info->dlpi_phdr[i].p_memsz;
|
||||
if (start < libStart)
|
||||
libStart = start;
|
||||
if (end > libEnd)
|
||||
libEnd = end;
|
||||
if (start < firstMappingStart) {
|
||||
firstMappingStart = start;
|
||||
}
|
||||
if (end > lastMappingEnd) {
|
||||
lastMappingEnd = end;
|
||||
}
|
||||
}
|
||||
|
||||
libInfoList->AppendElement(LoadedLibraryInfo(dl_info->dlpi_name,
|
||||
libStart, libEnd));
|
||||
libInfoList->AppendElement(LoadedLibraryInfo(dl_info->dlpi_name, baseAddress,
|
||||
firstMappingStart, lastMappingEnd));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -244,7 +250,10 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
|
|||
|
||||
for (const auto& libInfo : libInfoList) {
|
||||
info.AddSharedLibrary(
|
||||
SharedLibraryAtPath(libInfo.mName.get(), libInfo.mStart, libInfo.mEnd));
|
||||
SharedLibraryAtPath(libInfo.mName.get(),
|
||||
libInfo.mFirstMappingStart,
|
||||
libInfo.mLastMappingEnd,
|
||||
libInfo.mFirstMappingStart - libInfo.mBaseAddress));
|
||||
}
|
||||
|
||||
#if defined(GP_OS_linux)
|
||||
|
|
|
@ -103,9 +103,10 @@ interface nsIProfiler : nsISupports
|
|||
* Every object has the properties:
|
||||
* - start: The start address of the memory region occupied by this library.
|
||||
* - end: The end address of the memory region occupied by this library.
|
||||
* - offset: Usually zero, except on Android if the region was mapped from
|
||||
* a file (using mmap), then this is the offset in the file where
|
||||
* the mapping begins.
|
||||
* - offset: Usually zero, except on Linux / Android if the first mapped
|
||||
* section of the library has been mapped to an address that's
|
||||
* different from the library's base address.
|
||||
* Then offset = start - baseAddress.
|
||||
* - name: The name (file basename) of the binary.
|
||||
* - path: The full absolute path to the binary.
|
||||
* - debugName: On Windows, the name of the pdb file for the binary. On other
|
||||
|
|
Загрузка…
Ссылка в новой задаче