Giter Club home page Giter Club logo

smalidea's Introduction

smalidea is a smali language plugin for IntelliJ IDEA/Android Studio

It is currently very experimental, and you will likely run into issues.

News

  • 2021-03-02 - v0.06 is out. This brings smalidea back up to snuff with regards to modern versions of IDEA/Android Studio

    • This force updates the smali file type to be associated with this plugin instead of the built-in smali plugin in Android Studio
    • This adds support for the new synaxes (hidden api restrictions, spaces in identifiers, etc.)
    • This fixes a problem with how registers were mapped on art while debugging (thanks @bet4it)
    • Structure view for smali files (thanks @Donlon)
  • 2020-02-23 - smalidea has been migrated to a separate repository. This new repository is a filtered copy of the original smali repository in order to maintain the git history. However, any versions prior to this migration are not expected to actually build. If you need to build an old version for some reason, you should check out and build from the smali repository.

  • 2016-02-27 - v0.03 is out. This is mostly a stability/bug fix release, with no significant new functionality.

Features

Current Features

  • Syntax Highlighting/Syntax Errors
  • Bytecode level debugging
    • Breakpoints
    • Instruction level single stepping
    • Adding watches for arbitrary (non-named) registers
    • Full java-style expression support in locals window, etc. while debugging
  • Go to Definition
  • Find Usages
  • Renaming
  • Referencing smali classes from java code (except it can't actually be compiled, yet)
  • Issue reporting - easily create a new github issue from the error dialog

Possible Future Features

  • Auto-complete (instruction names, class/method/field references, etc.)
  • Compile support for smali-only projects
  • Robust error detection (e.g. full bytecode verification)
  • Smoother project import process
    • Automatic detection of source directory
    • Choosing sdk
  • Wizard for importing an apk as a new project
  • "Smali Class" entry in "New..." context menu
  • Show all registers with a value in "locals" pane
  • Ability to set the value of a register in "watch" pane

"Stretch" Features

  • Compile support for mixed smali+java projects
  • "Introduce new register" intention
  • Import (and deodex) device framework as new module (or new sdk??)
  • Expose register type analysis data
    • Show the expected type of a register at any point
    • Find locations where the register's value could have been set

Installation

  1. Download the latest smalidea zip file from the Bitbucket download page
  2. In IDEA/AS, go to Settings->Plugins and click the "Install plugin from disk" button, selecting the downloaded smalidea zip file
  3. Click "Apply" and restart IDEA/AS
  4. ???
  5. Profit!

Debugging an application

Note: Single-instruction stepping is only supported in IDEA 14.1 and greater, and any future version of Android Studio based on IDEA 14.1 or greater. In earlier versions, attempting to single step will step to the next .line directive, instead of stepping to the next instruction.

  1. Manually disassemble an application using baksmali into a "src" subdirectory of a new project directory, e.g. baksmali d myapp.apk -o ~/projects/myapp/src
  2. In IDEA, import a new project, and select the project directory. e.g. ~/projects/myapp
  3. Use the "Create project from existing sources" option when importing the project
  4. Once the project has been created, right click on the src directory and select "Mark Directory As->Sources Root"
  5. Open the project settings and select/create an appropriate JDK
  6. Install/start the application on the device
  7. Run adb shell ps | grep <package-name> and take note of the pid of the application process
  8. run adb forward tcp:8700 jdwp:<pid>
  9. In IDEA, Create a new "Remote" debug configuration (Run->Edit Configurations), and change the debug port to 8700
  10. Run->Debug
  11. The application should pause if/when the breakpoint is hit, at which point you can single step, add watches, etc.

or do the following in recent Android Studio 3.2:

  1. Manually disassemble an application using baksmali into a "src" subdirectory of a new project directory, e.g. baksmali d myapp.apk -o ~/projects/myapp/src
  2. In Android Studio, close your current project and select "Open an existing Android Studio project".
  3. Once the project has been created, right click on the src directory and select "Mark Directory As->Sources Root"
  4. Make sure your app has android:debuggable="true" in Android Manifest. Turn on "USB debugging" and use "Select debug app" to select your app in "Developer options" on Android device
  5. Install/start the application on the device
  6. Run adb shell ps | grep <package-name> and take note of the pid of the application process
  7. run adb forward tcp:8700 jdwp:<pid>
  8. In Android Studio, Create a new "Remote" debug configuration (Run->Edit Configurations), and change the debug port to 8700
  9. In Android Studio, select Run -> Debug
  10. The application should pause if/when the breakpoint is hit, at which point you can single step, add watches, etc.

smalidea's People

Contributors

agorski3 avatar bet4it avatar donlon avatar jesusfreke avatar mikaelpeltier avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smalidea's Issues

Release new version

I see a lot of changes since 31 March 2017. Could you please make a release for this one if these changes are significant enough?

Error install plugin for IDEA/AS

According to the instruction I downloaded smali-2.4.0.jar, but when I choose Plugin->Install Plugin from Disk... and choose this file, it gives me an error: Fail to load plugin descriptor from file smali-2.4.0.jar. The problem occurs both in IDEA and AS. How to solve it?

Smali evaluation not working

AWESOME tool, really awesome tool.
Don't know if this is a known limitation, but Smali evaluation does not work, while Java one does. It would be really helpful to get the Smali one working as well otherwise it's not possible to tamper with the registers on-the-fly.

image

Can't Import into Android Studio

I'm using Android Studio 3.6.1 and getting the error

Fail to load plugin descriptor from file smali-2.4.0.jar

Any idea? Thanks

Error Encountered while Installing Smalidea Plugin on Android Studio 2022.2.1

Hello,

I'm facing difficulties while attempting to use the Smalidea plugin on Android Studio 2022.2.1 (Build #AI-222.4459.24.2221.9862592, built on March 31, 2023, Runtime version: 17.0.6+0-b2043.56-9586694 amd64).

I keep encountering the following error message:
"Plugin 'Smalidea' is compatible with IntelliJ IDEA only because it doesn't define any explicit module dependencies."

I tried adding the following lines to the plugin.xml file:
<depends>com.intellij.modules.androidstudio</depends>

However, this only worsened the situation.

I would greatly appreciate any assistance!

java.lang.NoClassDefFoundError: com/intellij/psi/PsiElementFinder Android Studio 4.1.2

Added "com.intellij.modules.androidstudio" to plugin.xml in smalidea-0.05.zip and installed plugin into Android Studio 4.1.2, but found an error during smali open:

com.intellij.diagnostic.PluginException: While loading class org.jf.smalidea.psi.index.SmaliClassFinder: com/intellij/psi/PsiElementFinder [Plugin: org.jf.smalidea]
	at com.intellij.ide.plugins.cl.PluginClassLoader.loadClassInsideSelf(PluginClassLoader.java:262)
	at com.intellij.ide.plugins.cl.PluginClassLoader.tryLoadingClass(PluginClassLoader.java:205)
	at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:113)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at com.intellij.openapi.extensions.impl.ExtensionComponentAdapter.getImplementationClass(ExtensionComponentAdapter.java:80)
	at com.intellij.openapi.extensions.impl.ExtensionComponentAdapter.createInstance(ExtensionComponentAdapter.java:39)
	at com.intellij.openapi.extensions.impl.XmlExtensionAdapter.createInstance(XmlExtensionAdapter.java:68)
	at com.intellij.openapi.extensions.impl.ExtensionPointImpl.processAdapter(ExtensionPointImpl.java:446)
	at com.intellij.openapi.extensions.impl.ExtensionPointImpl.processAdapters(ExtensionPointImpl.java:401)
	at com.intellij.openapi.extensions.impl.ExtensionPointImpl.getExtensionList(ExtensionPointImpl.java:232)
	at com.intellij.psi.impl.JavaPsiFacadeImpl.finders(JavaPsiFacadeImpl.java:203)
	at com.intellij.psi.impl.JavaPsiFacadeImpl.filteredFinders(JavaPsiFacadeImpl.java:245)
	at com.intellij.psi.impl.JavaPsiFacadeImpl.findPackage(JavaPsiFacadeImpl.java:219)
	at com.intellij.psi.impl.file.JavaDirectoryServiceImpl.getPackage(JavaDirectoryServiceImpl.java:60)
	at com.intellij.ide.projectView.impl.JavaProjectViewDirectoryHelper.getNodeName(JavaProjectViewDirectoryHelper.java:61)
	at com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode.updateImpl(PsiDirectoryNode.java:127)
	at com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode.lambda$doUpdate$1(AbstractPsiBasedNode.java:166)
	at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:864)
	at com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode.doUpdate(AbstractPsiBasedNode.java:141)
	at com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode.lambda$update$0(AbstractPsiBasedNode.java:137)
	at com.intellij.util.AstLoadingFilter.lambda$toComputable$2(AstLoadingFilter.java:168)
	at com.intellij.util.AstLoadingFilter.disallowTreeLoading(AstLoadingFilter.java:126)
	at com.intellij.util.AstLoadingFilter.disallowTreeLoading(AstLoadingFilter.java:115)
	at com.intellij.util.AstLoadingFilter.disallowTreeLoading(AstLoadingFilter.java:110)
	at com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode.update(AbstractPsiBasedNode.java:137)
	at com.intellij.ide.util.treeView.PresentableNodeDescriptor.getUpdatedPresentation(PresentableNodeDescriptor.java:74)
	at com.intellij.ide.util.treeView.PresentableNodeDescriptor.update(PresentableNodeDescriptor.java:27)
	at com.intellij.ui.tree.StructureTreeModel$Node.update(StructureTreeModel.java:453)
	at com.intellij.ui.tree.StructureTreeModel$Node.<init>(StructureTreeModel.java:435)
	at com.intellij.ui.tree.StructureTreeModel$Node.<init>(StructureTreeModel.java:427)
	at com.intellij.ui.tree.StructureTreeModel$Node.<init>(StructureTreeModel.java:421)
	at com.intellij.ui.tree.StructureTreeModel.getValidChildren(StructureTreeModel.java:391)
	at com.intellij.ui.tree.StructureTreeModel.validateChildren(StructureTreeModel.java:298)
	at com.intellij.ui.tree.StructureTreeModel.getNode(StructureTreeModel.java:292)
	at com.intellij.ui.tree.StructureTreeModel.getChildren(StructureTreeModel.java:312)
	at com.intellij.ui.tree.AsyncTreeModel$CmdGetChildren.getNode(AsyncTreeModel.java:573)
	at com.intellij.ui.tree.AsyncTreeModel$ObsolescentCommand.get(AsyncTreeModel.java:468)
	at com.intellij.ui.tree.AsyncTreeModel$ObsolescentCommand.get(AsyncTreeModel.java:434)
	at com.intellij.util.concurrency.Invoker$Task.run(Invoker.java:323)
	at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1109)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runInReadActionWithWriteActionPriority$0(ProgressIndicatorUtils.java:75)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.lambda$runWithWriteActionPriority$1(ProgressIndicatorUtils.java:129)
	at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:166)
	at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:627)
	at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:572)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:61)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:153)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runWithWriteActionPriority(ProgressIndicatorUtils.java:118)
	at com.intellij.openapi.progress.util.ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(ProgressIndicatorUtils.java:75)
	at com.intellij.util.concurrency.Invoker.invokeSafely(Invoker.java:206)
	at com.intellij.util.concurrency.Invoker.lambda$offerSafely$0(Invoker.java:184)
	at com.intellij.util.concurrency.Invoker$Background.lambda$offer$0(Invoker.java:524)
	at com.intellij.util.concurrency.BoundedTaskExecutor.doRun(BoundedTaskExecutor.java:222)
	at com.intellij.util.concurrency.BoundedTaskExecutor.access$200(BoundedTaskExecutor.java:29)
	at com.intellij.util.concurrency.BoundedTaskExecutor$1.execute(BoundedTaskExecutor.java:201)
	at com.intellij.util.ConcurrencyUtil.runUnderThreadName(ConcurrencyUtil.java:210)
	at com.intellij.util.concurrency.BoundedTaskExecutor$1.run(BoundedTaskExecutor.java:190)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: com/intellij/psi/PsiElementFinder
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:636)
	at com.intellij.util.lang.UrlClassLoader._defineClass(UrlClassLoader.java:380)
	at com.intellij.util.lang.UrlClassLoader.defineClass(UrlClassLoader.java:376)
	at com.intellij.util.lang.UrlClassLoader._findClass(UrlClassLoader.java:340)
	at com.intellij.ide.plugins.cl.PluginClassLoader.loadClassInsideSelf(PluginClassLoader.java:259)
	... 61 more
Caused by: java.lang.ClassNotFoundException: com.intellij.psi.PsiElementFinder PluginClassLoader[org.jf.smalidea, 0.05] com.intellij.ide.plugins.cl.PluginClassLoader@9e2941d
	at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:115)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
	... 68 more

Readme tutorial ("Debugging an application") not completely understandable

I understand that this section was written for Android Studio 3.2, not for the current version. I tried to follow but it was hardly possible.
to improve user experience of others some suggestions/additions for the readme

step 1: "baksmali" is to be used. If I use C:\Program Files\Android\Android Studio\plugins\android\lib\baksmali-2.2.4.jar like that I get "no main manifest attribut" error. Googeling for baksmali I found https://github.com/JesusFreke/smali. The latest release there is baksmali-2.0b6.jar - this does not have the "main missing in manifest"-issue, but it seems to work not on .apk, but on .dex (extracted from an apk, probably). finally I stumbled across https://bitbucket.org/JesusFreke/smali/downloads/ where version 2.5.2 can be found and this version works. Later I noticed that readme.md of github.com/JesusFreke/smali references the bitbucked. I think it would be good to mention the bitbucked in the smalidea readme and to create a pseudo-github-release or update the description of the last github-release to mention that newer und upcomming updates will be available in the bitbucket (and not as github-releases)

step 2: does not specify the directory (~/projects/myapp). Furthermore, there is only "Open" not "Open an existing Android Studio project"
setp 3: "Once the project has been created" - this is confusing. step 2 says, we just open an existing project, now you say we created one?!
step 4: android:debuggable="true" in the manifest is a parameter of the <application - XML-Tag in the Manifest. I think this should be mentioned before step 1, because if this is not set already then one needs to change the apk and extract the changed apk in step 1 again
step 8: new "Remote" debug configuration seems to be called "Remote JVM Debug" (now). If I debug, in Android studio in the "Debugger" tag in the "debug" section I do only see "Connecting to the target VM, address: 'localhost:8700', transport: 'socket'" - not "connected". Breakpoints do not seem to work either.

Run -> "Attach debugger to Android proceess" works and it does not need the adb forward part.

[BUG] after installing studio fails to launch

Internal error. Please refer to https://code.google.com/p/android/issues

com.intellij.ide.plugins.PluginManagerCore$EssentialPluginMissingException: Missing essential plugins: com.android.tools.design, org.jetbrains.android
at com.intellij.ide.plugins.PluginManagerCore.checkEssentialPluginsAreAvailable(PluginManagerCore.java:761)
at com.intellij.ide.plugins.PluginManagerCore.initializePlugins(PluginManagerCore.java:854)
at com.intellij.ide.plugins.PluginManagerCore.initializeAndSetPlugins(PluginManagerCore.java:1068)
at com.intellij.ide.plugins.PluginDescriptorLoader$scheduleLoading$pluginSetDeferred$1.invokeSuspend(PluginDescriptorLoader.kt:397)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)


Your JRE: 17.0.7+0-17.0.7b829.16-10353782 aarch64 (JetBrains s.r.o.)
/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home

Edit variables and read-only files

Is there any option to edit watches?¿ I see I can edit the value in "this", but I cant figure out how to edit for example the v0 value while debugging.
Also, I tried to edit smali files but those appear as "read-only", is there any chance to modify those files and recompile app (I suppose this is harder than the other)

Rename class function not working fully

When refactor-rename class it doesn't rename quoted string class names in the body of annotation,

 .annotation system Ldalvik/annotation/Signature;
   value = {
     "Ljava/lang/Object;",
     "Lcom/some/OldClassName<",
     "Ljava/lang/Object;",
     ">;"
   }
 .end annotation

evaluate and log in breakpoint logs value only from first evaluation

My software setup:

Android Studio Bumblebee | 2021.1.1 Patch 1
Build #AI-211.7628.21.2111.8139111, built on February 1, 2022
Runtime version: 11.0.11+9-b60-7590822 amd64
VM: OpenJDK 64-Bit Server VM by Oracle Corporation
Windows 10 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 1280M
Cores: 8
Registry: external.system.auto.import.disabled=true
Non-Bundled Plugins: com.github.beansoft.jadx.gui.idea (2021.2.1), org.jf.smalidea (0.06-dev), PythonCore (211.7628.24), org.jetbrains.kotlin (211-1.6.10-release-923-AS7442.40)

My problem

For debugged method below evaluate and log output is same for all calls.

Breakpoint configuration

obraz

Debugged method

.method public static a(I)I
    .registers 2

    .line 108
    sget-object v0, Lcom/badlogic/gdx/math/MathUtils;->a:Ljava/util/Random;

    add-int/lit8 p0, p0, 0x1

    invoke-virtual {v0, p0}, Ljava/util/Random;->nextInt(I)I #breakpoint evaluating p0

    move-result p0 

    return p0 #breakpoint evaluating p0
.end method

Output:

random 3
random_result 1
random 3
random_result 1
random 3
random_result 1
random 3
random_result 1

In watches I can see value correctly changing with each call.

Watches values:

obraz

[Feature request] Side by side view with decompiled Java code

First of all I would like to thank the author for this great extension! This functionality really should be built into the IDE.

Would it be possible to implement a side by side view with decompiled Java code? Something similar to Ghidra, where you can see the Smali file in one window and an approximate Java equivalent (could be generated by JADX). It could look something like the split view with XML layout files in Android Studio, for example.

This feature would be really helpful when debugging an application. Unfortunately I don't have experience building IntelliJ plug-ins, so it would be great if someone can at least provide an overview of what would be required to implement this feature.

When steping the code, nothing is shown on the variables view

Hello,

when steping the code nothing is shown. I'm using a rooted phone with the wikipedia app to test.
What I do:

  1. put app in debuggable state and repack
  2. use developer mode to select app and tick "wait for debugger"
  3. Attach to the process using idea

Breakpoint are hit, and I can step put I get no info at all...
For example:

  new-instance v0, Lorg/wikipedia/main/MainActivity$Companion;

    const/4 v1, 0x0

When I step the new instance, I should see v0 in the variables.
Inside the variables, I see: "static members of MainActivity", then I click on it and I see: Collecting Data... and It never ends.
Is there a way to debug the plugin ?

MacBook M1 breakpoint not work.

MacBook M1
Android studio 4.0.2
already connect to pixel4 (Android 11)
but breakpoint not work.

win10 work well with pixel4(Android 11)

Cannot get local variables in a method

I have not been using smalidea for some time, but I remember when it hits the break points, I could see the value of local variables v0, v1.., p0, p1...
However, it says internal like this now:
螢幕快照 2020-04-18 下午1 14 20

EDIT
It does work for objects, but not primitives.

According to the instruction I downloaded smalidea-0.05.zip from github, but when I choose Plugin->Install Plugin from Disk... and choose this file, it gives me an error: Fail to load plugin descriptor from file smalidea-0.05.zip. The problem occurs both in IDEA and AS. How to solve it?

According to the instruction I downloaded smali-2.4.0.jar, but when I choose Plugin->Install Plugin from Disk... and choose this file, it gives me an error: Fail to load plugin descriptor from file smali-2.4.0.jar. The problem occurs both in IDEA and AS. How to solve it?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.